Java String... question regarding multiple inputs for a method - java

is it possible to create a class and have a String ... attribute that takes as many or as little strings as you put?
example:
please excuse my rough pseudocode, this is for java.
//this is the method:
public void getXXXX(String ...) {
//random code executes in a loop with as many as strings that are inputted
}
//this code calls it
getXXXX("Benjamin","Jordan","Steve")
getXXXX("Pengu","No")
getXXXX("hi")

Yes, what you entered will more or less work, you just need a parameter name after your type.
class StringDecorator {
public static String join(final String... strings) {
final var builder = new StringBuilder();
for (final var string : strings) {
builder.append(string);
}
return builder.toString();
}
}
Then invoke this somewhere
StringDecorator.join("Hello, ", "World!"); // "Hello, World!"

Related

how many time the characters of string are to be found in another string

my professor gave me an exercise to find how many time the characters of string called "filter" are to be found in a second string called "query".
before I begin I am java noob and English isnt my native language.
example:
String filter="kjasd";
String query="kjg4t";
Output:2
getting how many times a char has been found in another string isnt my problem but the problem that the professor gave us some rules to stick with:
class filter. The class must be the following public
Provide interfaces:
public Filter (String letters) (→ Constructor of class)
The string representing the filter should be stored in the letters string
public boolean contains (char character)
Returns true if the passed character is contained in the query string, otherwise false
-public String toString ()
Returns an appropriate string representation of the class (just to be clear I have no clue about what does he means with this one!)
To actually determine the occurrences of the filter in the query, another class QueryResolver is to be created.
The class should be able to be used as follows:
QueryResolver resolver = new QueryResolver();
int count = resolver.where(query).matches(filter).count();
the filter and the query are given by the user.
(i couldnt understand this one! )The methods "where" and "matches" configure the "QueryResolver" to include a subsequent call of "count" the calculation based on the previously passed variables
"query" and "filter" performs.
The count method should use the filter's previously-created method.
The modifier static is not allowed to use!
I dunno if he means that we cant use static {} or we cant use public (static) boolean contains (char character){}
we are not allowed to use void
so the problems that encountered me
- I can not pass a char to the method contains as long as it is not static.
error "Non-static variable can not be referenced from a static context"
i did not understand what i should do with the method toStirng!
what I've done so far:
Approach Nr 1:
so I just wrote everything in the main method to check whether the principle of my code works or not and then I wanted to create that whole with constructor and other methods but unfortunately I did not succeed.
Approach Nr 2:
then I tried to write the code in small mthoden as in the exercise but I did not succeed !.
in both aprroaches i violated the exercise rules but i cant seem to be able to do it alone thats why i posted the question here.
FIRST APPROACH:
public class filter{
public filter(String letters) {
//constructor of the class
String filter;
int count;
}
public boolean contains (char character){
/*Subprogram without static!
*the problem that I can't pass any char to this method if it wasn't static
*and I will get the following error"Non-static variable cannot be referenced from a static context"
*I understand why I'm getting the error but I don't know how to get around it X( */
return true ;
}
public String toString (){
/*he told us to include it in the program but honestly, I don't know what shall I write in it -_-
*I make it to null because you have to return something and I don't know what to do yet
*so, for now, I let it null. */
return null;
}
public static void main(String[] args) {
Scanner in =new Scanner (System.in);
System.out.println("please enter the query string! ");
String query= in.next();
System.out.println("please enter the filter stirng!");
String filter= in.next();
System.out.println("the query string is : [" + query+ "]");
System.out.println("the filter string is : [" + filter+ "]");
int count=0;
// I initialized it temporarily because I wanted to print it!
//later I need to use it with the boolean contains as a public method
boolean contains=false;
//to convert each the query and the filter strings to chars
char [] tempArray=query.toCharArray();
char [] tempArray1=filter.toCharArray();
//to iterate for each char in the query string!
for (int i = 0; i < tempArray.length; i++) {
char cc = tempArray[i];
//to iterate for each char in the filter string!
for (int j = 0; j < tempArray1.length; j++) {
// if the value in the filter string matches the value in the temp array then increment the counter by one!
if(tempArray1[j] == cc){
count++;
contains=true;
}
}
}
System.out.println("the characters of the String ["+filter+"] has been found in the forworded string ["+query+"] exactly "+count+" times!" );
System.out.println("the boolean value : "+ contains);
in.close();
}
}
SECOND APPROACH
- But here too I violated the rules of the task quite brutally :(
- First, I used void and did not use the tostring method.
- Second, I did not use a constructor.
- I did not add comments because that's just the same principal as my first attempt.
public class filter2 {
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
System.out.println("enter the filter string:");
String filterStr=in.next();
System.out.println("enter the query string:");
String querystr =in.next();
Filter(filterStr, querystr);
in.close();
}
public static void Filter(String filterstr , String querystr){
char [] tempArray1 = filterstr.toCharArray();
contains(tempArray1, querystr);
}
public static void contains(char[]tempArray1, String querystr){
boolean isThere= false ;
int counter=0;
char [] tempArray = querystr.toCharArray();
for (int i = 0; i < tempArray.length; i++) {
char cc = tempArray[i];
for (int j = 0; j < tempArray1.length; j++) {
if(tempArray1[j] == cc){
counter++;
isThere=true;
}
}
}
System.out.println("the letters of the filter string has been found in the query string exactly "+counter+" times!\nthus the boolean value is "+isThere);
}
/*
* sadly enough i still have no clue what is meant with this one nor whatshall i do
* public String toString (){
* return null;
* }
*
*/
}
Few hints and advice would be very useful to me but please demonstrate your suggestions in code because sometimes it can be difficult for me to understand what you mean by the given advice. ;)
Thank you in advance.
(sorry for the gramatical and the type mistakes; english is not my native language)
As already mentioned, it is important to learn to solve those problems yourself. The homework is not for punishment, but to teach you how to learn new stuff on your own, which is an important trait of a computer scientist.
Nonetheless, because it seems like you really made some effort to solve it yourself already, here is my solution, followed by some explanation.
General concepts
The first thing that I feel like you didn't understand is the concept of classes and objects. A class is like a 'blueprint' of an object, and the object is once you instanciated it.
Compared with something like a car, the class would be the description how to build a car, and the object would be a car.
You describe what a class is with public class Car { ... }, and instanciate an object of it with Car myCar = new Car();.
A class can have methods(=functions) and member variables(=data).
I just repeat those concepts because the code that you wrote looks like you didn't fully understand that concept yet. Please ask some other student who understood it to help you with that.
The Filter class
public class Filter{
String letters;
public Filter(String letters) {
this.letters = letters;
}
public boolean contains (char character){
for(int i = 0; i < letters.length(); i++) {
if(letters.charAt(i) == character)
return true;
}
return false;
}
public String toString (){
return "Filter(" + letters + ")";
}
}
Ok, let's brake that down.
public class Filter{
...
}
I guess you already got that part. This is where you describe your class structure.
String letters;
This is a class member variable. It is unique for every object that you create of that class. Again, for details, ask other students that understood it.
public Filter(String letters) {
this.letters = letters;
}
This is the constructor. When you create your object, this is the function that gets called.
In this case, all it does is to take an argument letters and stores it in the class-variable letters. Because they have the same name, you need to explicitely tell java that the left one is the class variable. You do this by adding this..
public boolean contains (char character){
for(int i = 0; i < letters.length(); i++) {
if(letters.charAt(i) == character)
return true;
}
return false;
}
This takes a character and looks whether it is contained in this.letters or not.
Because there is no name collision here, you can ommit the this..
If I understood right, the missing static here was one of your problems. If you have static, the function is class-bound and not object-bound, meaning you can call it without having an object. Again, it is important that you understand the difference, and if you don't, ask someone. (To be precise, ask the difference between class, object, static and non-static) It would take too long to explain that in detail here.
But in a nutshell, if the function is not static, it needs to be called on an object to work. Look further down in the other class for details how that looks like.
public String toString (){
return "Filter(" + letters + ")";
}
This function is also non-static. It is used whenever the object needs to be converted to a String, like in a System.out.println() call. Again, it is important here that you understand the difference between class and object.
The QueryResolver class
public class QueryResolver {
Filter filter;
String query;
public QueryResolver where(String queryStr) {
this.query = queryStr;
return this;
}
public QueryResolver matches(String filterStr) {
this.filter = new Filter(filterStr);
return this;
}
public int count() {
int result = 0;
for(int i = 0; i < query.length(); i++) {
if(filter.contains(query.charAt(i))){
result++;
}
}
return result;
}
}
Again, let's break that down.
public class QueryResolver {
...
}
Our class body.
Note that we don't have a constructor here. It is advisable to have one, but in this case it would be an empty function with no arguments that does nothing, so we can just leave it and the compiler will auto-generate it.
public QueryResolver where(String queryStr) {
this.query = queryStr;
return this;
}
This is an interesting function. It returns a this pointer. Therefore you can use the result of the function to do another call, allowing you to 'chain' multiple function calls together, like resolver.where(query).matches(filter).count().
To understand how that works requires you to understand both the class-object difference and what exactly the this pointer does.
The short version is that the this pointer is the pointer to the object that our function currently lives in.
public QueryResolver matches(String filterStr) {
this.filter = new Filter(filterStr);
return this;
}
This is almost the same as the where function.
The interesting part is the new Filter(...). This creates the previously discussed Filter-object from the class description and puts it in the QueryResolver object's this.filter variable.
public int count() {
int result = 0;
for(int i = 0; i < query.length(); i++) {
if(filter.contains(query.charAt(i))){
result++;
}
}
return result;
}
Iterates through the object's query variable and checks for every letter if it is contained in filter. It keeps count of how many times this happens and returns the count.
This function requires that filter and query are set. Therefore it is important that before someone calls count(), they previously call where(..) and matches(..).
In our case, all of that happens in one line, resolver.where(query).matches(filter).count().
The main function
I wrote two different main functions. You want to test your code as much as possible during development, therefore the first one I wrote was a fixed one, where you don't have to enter something manually, just click run and it works:
public static void main(String[] args) {
String filter="kjasd";
String query="kjg4t";
QueryResolver resolver = new QueryResolver();
int count = resolver.where(query).matches(filter).count();
System.out.println(count);
}
Once you understand the class-object difference, this should be straight forward.
But to repeat:
QueryResolver resolver = new QueryResolver();
This creates your QueryResolver object and stores it in the variable resolver.
int count = resolver.where(query).matches(filter).count();
Then, this line uses the resolver object to first call where, matches, and finally count. Again, this chaining only works because we return this in the where and matches functions.
Now finally the interactive version that you created:
public static void main(String[] args) {
Scanner in =new Scanner(System.in);
System.out.println("please enter the query string! ");
String query= in.next();
System.out.println("please enter the filter stirng!");
String filter= in.next();
System.out.println("the query string is : [" + query+ "]");
System.out.println("the filter string is : [" + filter+ "]");
QueryResolver resolver = new QueryResolver();
int count = resolver.where(query).matches(filter).count();
System.out.println("the characters of the String ["+filter+"] has been found in the forworded string ["+query+"] exactly "+count+" times!" );
in.close();
}

How to convert a String which looks like an Array into an actual Object Array?

Since
public static String requestMethodExecution(String objectName, String className, String methodName, Object...
params) {
return String.format("%s,%s,%s,%s", objectName, className, methodName, Arrays.toString(params));
}
returns a String, and if you would, for example, call the method like this:
requestMethodExecution("foo","bar","fooBar",2.0,3.0,"Hello");
You'd get a String like this: foo,bar,fooBar,[2.0,3.0,Hello]
I would love to iterate over that Array, but I can't since it is a String.
Reason behind this is this method: (I just started with reflection, so I do not know how else to do it)
public static Class[] getParameterType(String ...params) throws ClassNotFoundException {
Class[] paramTypes = new Class[params.length];
for(int i=0; i<params.length;i++){
Class paramClass = Class.forName(params[i]);
if (paramClass == Double.class) {
paramTypes[i] = (double.class);
} else if (paramClass == Integer.class) {
paramTypes[i] = (int.class);
} else {
paramTypes[i] = paramClass;
}
}
return paramTypes;
}
So far I have only come up with a very dirty way:
public static String[] getParams(String message){
int indexOfParamStart = message.indexOf("[");
int indexOfParamEnd = message.indexOf("]")+1;
String[] splitMessage = message.substring(indexOfParamStart, indexOfParamEnd).replaceAll("\\[", "")
.replaceAll("]", "").replaceAll(" ","").split(",");
return splitMessage;
}
Edit: Thanks for looking into this! Since some of you are asking what I am trying to achieve, here is a bit more explanation:
I want to implement a simple request/reply protocol which allows remote method invocation (and I do not want to use java RMI...)
So I listen for requests whose structure can be seen at the requestMethodExecution example.
There I have all the relevant information to call the Method upon my class, so to invoke the method I need it's arguments (and their value) and I do not know how to access them from the given String.
The others are easy with Class c = Class.forName(className); etc..
Edit#2:
My question is not about a simple regex, so why close it? The title already states a different subject, I am getting a bit salty here...
See this this question for using RegEx to extract the array body from the outer string (by the square brackets), and then you can simply use String.split(",") to split the array body into array items.

Creating a static method that meshes two strings together

We recently started learning about static methods and for this assignment we are making a "String Helper" program that creates a few static methods that modify strings, and this is the task for one of them:
meshStrings: This method takes in two strings via parameters, meshes them together, and returns the meshed strings. Meshing alternates the each character in the first string with every character in the next string. If there are not enough characters to fully mesh then the rest will be appended to the end. For instance if the two strings were "harp" and "fiddle" the returned string will be hfairdpdle.
Here's the start of what I have, I don't have much:
public class StringHelper {
public static String meshStrings (String string1, String string2)
{
}
Driver class:
public class StringHelperTester {
public static void main (String[] args)
{
System.out.print(StringHelper.meshStrings("fiddle", "harp"));
}
I assume you'll have some type of for loop that prints out the charAt length of each string but I'm not exactly sure the best way to set it up. Help is appreciated.
the best way to enchance your skills is to just try ...
public static String meshStrings (String string1, String string2) {
StringBuffer buff = new StringBuffer();
int max = Math.max(string1.length(), string2.length());
for(int i = 0; i < max; i++) {
if(i < string1.length()) {
buff.append(string1.charAt(i));
}
if(i < string2.length()) {
buff.append(string2.charAt(i));
}
}
return buff.toString();
}
KISS : keep it simple and stupid. then you can enhance this code if you want, it's not optimal.

How can I substitute an arbitrary number of substrings?

I'm working on a basic RPC design. From a listener, I retrieve a desired RPC like:
ArrayList<String> params = new ArrayList<String>();
params.add(Node.getLocal().getHostname());
params.add("test");
RPC rawRPC = StorageControl.getRPC(StorageControl.RPC_HelloMaster, params));
My StorageControl class is pretty simple right now,
public class StorageControl {
public StorageControl(){
availableRPCs.put(RPC_HelloMaster, new RPC("[%s] Hello, Master. [%s]"));
}
public static final String RPC_HelloMaster = "helloMaster";
private static String MasterHostname;
public static String getMaster(){ return MasterHostname; }
public static void setMaster(String host){ MasterHostname = host; }
private static Map<String, RPC> availableRPCs = new HashMap<String, RPC>();
public static RPC getRPC(String key, ArrayList<String> params) {
RPC rawRPC = availableRPCs.get(key);
// This is what fails
for (String param : params){
rawRPC.msg = String.format(rawRPC.msg, param);
}
return rawRPC;
}
}
RPC is just a simple class, containing a single variable, msg
So, the idea is that I want to retrieve RPCs, that may have a variable number of variables that need substituted. Is there a more elegant way (that actually works) to do this? What I have now fails with a MissingFormatArgumentException, I assume because the first loop doesn't attempt to replace beyond the 1st variable.
At first we need to know how format works,
String x = String.format("%s %s","hello","world");
then x will have "hello world". But if we do this
String x = String.format("%s %s","hello");
It will give you a illegal argument exception because there are not enough arguments to replace.
So you need to pass all arguments at once. Now variable arguments actually array of args. So you can do this.
String stringToFormat = "%s %s %s";
String[] ags = {"hello","world","gg"};
stringToFormat = String.format(stringToFormat,ags);
System.out.println(stringToFormat);
In your case, you can just do this without loop
rawRPC.msg = String.format(rawRPC.msg, params.toArray(new String[params.size()]));

I have to test Java

I was told in my class that I have to write and test my code in the main method, I wrote it, but I dont know how to test it. How I am supposed to test my methods? I am supposed to take user input, and then get the get the first letter, last letter, etc.
import java.util.Scanner;
public class Word
{
public static void main(String[] args)
{
}
public String word;
public void Word()
{
String word = "";
}
public void Word(String word1)
{
String word = word1;
}
public String getWord()
{
return word;
}
public void setWord(String newWord)
{
String word = newWord;
}
public void getFirstLetter()
{
String firstLetter = word.substring(0, 1);
}
public void getLastLetter()
{
String lastLetter = word.substring(word.length() - 1, word.length());
}
public void removeFirstLetter()
{
String noFirstLetter = word.substring(1, word.length());
}
public void removeLastLetter()
{
String noLastLetter = word.substring(0, word.length() - 1);
}
public int findLetter (String parameter)
{
word.indexOf(parameter);
return 1;
}
}
You test your methods by calling them with some defined input and compare the results with your expected output.
Example:
Suppose you have a method like this:
public static int add(int a, int b) {
return a + b;
}
You'd test it like this:
int result = add( 3, 5);
if( result != 8 ) {
//method is wrong
}
So basically you define a "contract" of what input the method gets and what the result should be (in terms of return value or other changed state). Then you check whether you get that result for your input and if so you can assume the method works correctly.
In order to be quite sure (you often can't be perfectly sure) you'd test the method several times with different types of input (as many as reasonable, to test different cases, e.g. short words, long words).
You often also test how your method handles wrong input, e.g. by passing null or empty strings.
You should have a look at tools like junit.
You can create a simple Test class and test your class and its behavior.
imports ...;
public class MyTest{
#Test
public void testMyClass(){
Word w= new Word();
w.setWord("test");
Assert.assertEquals(w.getFirstLetter(), "t");
}
}
With tools like Eclipse you could nicely run such a test.
Just a hint: you're very close you need an instance of Word, than you can call your methods
public static void main(String[] args) {
Word test = new Word();
test.setWord("something");
// here you might read javadoc of the String class on how to compare strings
}
EDIT:
I overlooked this:
public void setWord(String newWord)
{
String word = newWord;
}
The code you've written creates a variable word and newWord is assigned to it and then disappears.
If you (obviously) want to set a member of a class you should use this wich references the instance (you created in main()).
public void setWord(String newWord) {
this.word = newWord;
}
Since I would say this is homework, I will try not to explicitly give the answer. In the main method, you should set your word, then call each method and print the output to verify it is correct.
Agree with Jason. If you wanna test something, simply System.out.println() it. In your methods though, your return type is not a String but a void, so you could change that, and print it out on the main program run.
If not, just put the System.out.println() in your void methods. Shouldn't have much of a problem!

Categories