Vararg initialization with parameters from array (Java) - java

Antescript: I'm aware that there's a prior SO question whose title sounds like it refers to the exact same question. It doesn't.
Anyway, this question is a little weird - there are plenty of better ways to work around the issues here, but I'm curious as to how I could solve my particular dilemma.
Let's say I have a method that uses varargs to accept an arbitrary number of elements, perhaps of type Integer. If I have an arbitrary-length array of Integers, is there a way for me to call my method with a comma-separated param list composed of each element of said array?
Here's a brief, contrived example:
Integer[] paramList = new Integer {1, 2, 3};
varMethod(paramList[0], paramList[1], paramList[2]);
// varMethod({{for (param : paramList) {param;}}});
public void varMethod(Integer...values) {
for (Integer value : values) {
foo(value);
}
}
That commented-out line hints at what I want to do. Since the paramList integer is arbitrary length, calling varMethod with each element explicitly requested (line 2) won't work. What I'm wondering is if there's a way to dynamically generate the comma-separated param list from the elements of an array.
Again, I realize that in an example like this, there are better ways to approach the entire problem, but please be aware that I've simplified the code so that it's only relevant to the particular issue we're discussing here. Any workarounds that address my posted code won't generalize to the problem I'm really working on that led me to formulate this question in the first place.

I think you're just looking for:
varMethod(paramList);
Perhaps you didn't realize that Integer... is a special variant of a normal Integer[] array. Thus since paramList is already an Integer[] array, you can just pass it directly into the method.

You can just call
varMethod(paramList);

Related

Why Do we have TwoPlusArrayList and OnePlusArrayList inside Lists class?

I am just curious about the Lists class implementation of google guava, we have two methods to create List from Array,
Lists.asList(E first, E[] rest)
Lists.asList(E first, E second, E[] rest)
Why do these methods has first and rest separately? cant it be like Arrays.asList implementation of java ?
The only thing I am able to see is the first and second is nullable and rest is not nullable
Can anyone help to understand this ?
Ok, so the job of the Lists.asList() is not exactly to directly convert an array to a list.
Suppose we have an array, and we want to insert an element to it, we can’t do it as the array size is fixed. One solution to this problem is to allocate an new array of +1 the size of the original array and copy all elements from the original array to the new array. This works but it is highly inefficient.
Guava provides an efficent solution to this problem – Guava’s Lists.asList() method returns an unmodifiable list backed by the original array which also contains the specified element.
source: https://www.techiedelight.com/guava-lists-class-java/
So basically, you can use it to just convert an array by giving the first and/or second parameters (depending upon what method you are using) as null, and giving the "rest" parameter as your array.
This will return your array as list, perhaps with null as the first index (and second as well, depending on what you are using)
But if you want, you can use the same methods to get a list with some specific data appended to your array (at first and second index values)
Hope this was helpful!
The main reason these methods exist is to help you when you write a method with a signature like
void foo(Bar first, Bar... rest);
which is something you'd do when you want to allow the user to call the method as if it were a method with just a varargs parameter, but you want to require that it be called with a minimum of one or two arguments (whereas varargs alone would allow them to call it with zero). In the implementation of such a method, you might want to treat those arguments as a single list. Lists.asList does that without doing any array copying:
void foo(Bar first, Bar... rest) {
List<Bar> bars = Lists.asList(first, rest);
// ...
}

Switch statement or remotely invoke methods

I have a switch statement that compares a String with set of String where each match calls a different method.
switch(((Operation) expr.getData()).getValue()){
case "+":
return add(expr.getNext());
case "car":
return car(expr.getNext());
case "cdr":
return cdr(expr.getNext());
case "cons":
return cons(expr.getNext(), expr.getNext().getNext());
case "quote":
return quote(expr.getNext());
case "define":
handleDefine(expr.getNext());
break;
default:
return null;
}
However, to me this sounds like something that could be achieved far more elegantly and efficiently using a HashMap that links up to an Operation that contains a Method and the number of parameters so I could each method to a HashMap like:
nameToOperation.put("+", new Operation("+", 1, Driver.class.getMethod("add")));
nameToOperation.put("car", new Operation("car", 1, Driver.class.getMethod("car")));
So there would be N different instances of the Operation class each containing the String, Method and number of parameters
And then I could simply call the method using something similar to this (I understand this isn't how you use invoke):
Operation op = ((Operation) expr.getData())
if(op.getNumPars() == 1)
return(op.getMethod().invoke(expr.getNext()));
else
return(op.getMethod().invoke(expr.getNext(), expr.getNext().getNext()));
However, I still don't fully like this solution as I am losing type safety and it still doesn't look that great. Another example I have seen on stackoverflow that looked quite elegant but I don't fully understand is the first solution of the top answer on: How to call a method stored in a HashMap? (Java)
What does everyone on Stackoverflow think the best solution is?
Edit: Just in case anybody searches this and was wondering about my solution, I made each operation such as Add, Car, Cdr have their own class that implemented Command. I then had to make the majority of my methods static, which I suppose by nature each of them were anyway. This seems way more elegant than the original case statement.
basicaly , the answer recommends to go with Command pattern.
"The main advantage of the command design pattern is that it decouples the object that invokes the operation from the one that know how to perform it. And this advantage must be kept. There are implementations of this design pattern in which the invoker is aware of the concrete commands classes. This is wrong making the implementation more tightly coupled. The invoker should be aware only about the abstract command class"
Basicaly your map would be type safety. by declaring
Map <character,Command>
Open to Extendibility
It looks like you are trying to write a Scheme interpreter. In that case you're gonna need a map anyway since you need to store all the user defined values und functions.
When the user writes e.g. (define (add a b) (+ a b)), you store the function in the map using "add" as key.
But your functions should use lists as inputs, i.e. each function has exactly one argument which is a list. In Scheme all expressions are lists by the way. Usually a Scheme interpreter consists of a reader and an evaluator. The reader converts the code into a bunch of nested lists.
So basically "(define (add a b) (+ a b))" could be converted into a list structure similar to this.
List<Object> list = new ArrayList<Object>();
List<Object> list2 = new ArrayList<Object>();
list2.add("add"); list2.add("a"); list2.add("b");
List<Object> list3 = new ArrayList<Object>();
list3.add("+"); list3.add("a"); list3.add("b");
list.add("define"); list.add(list1); list.add(list2);
Of course your code doesn't actually look like this, instead the lists are constructed by recursive methods parsing the input code.
Those lists don't just contain strings btw., they also contain numbers and boolean values. Nested lists like this are the most simple form of an abstract syntax tree (AST). Since the syntax of Scheme is much simpler than that of most other languages, a very simple list structure is enough to store the parsed code.
The evaluator then processes those lists.
To evaluate a list you first recursively evaluate every element in the list and then apply the first element to the rest of the list. That first element must therefore be a user defined function or a build in command e.g. "define".

Java - Indexing an Interface?

This is probably a really stupid question, so please forgive me. But this morning, I've come across a piece of Java syntax that I am completely unfamiliar with. The syntax is as follows:
public MyInterface[] getThings() {
return new MyInterface[0];
}
Obviously, I've changed the name of the interface, and of the method, but otherwise this code sample is unchanged.
I'm confused by this syntax, as it seems to be indexing an interface/class (not even an object)?! Also, the use of the new keyword, to instantiate an interface?!
I've genuinely attempted to Google this, in order to find an answer. But as it's syntax that I'm unfamiliar with, in addition to using the line of code itself as a search term, I've just been guessing at what terminology to use. And unfortunately, I've failed to find anything that explains this syntax for me. Hence, I'm hoping that someone on Stack Overflow might be kind enough to help me to understand this.
It's just creating an empty array. No instances of the interface are being created. It's equivalent to:
return new MyInterface[] { };
Or:
MyInterface[] array = {};
return array;
Specifically, it's an ArrayCreationExpression, as seen in section 15.10 of the JLS.
The function returns an empty array supposed to holding objects of type MyInterface.
It's similar as if you would use String[] to return an array of strings.
it just returns an empty array of MyInterface (size is 0). an array is an array, no matter, of which type the array is. it can be a primitive datatype, a class or an interface, too.

Adding all wrong answers into an array with Java - how?

I want to take all the questions that were answered incorrectly (it's a simple program asking math questions) and if they got the question wrong, add the question number to the array for further use.
But, I don't know how long this array will be, it could theoretically be of a different length each time the program is ran. So how would I set up the array?
You should use an ArrayList instead.
You could do something like:
ArrayList<String> wrongAnswers = new ArrayList<String>();
// Call this function with the user's answer as a parameter, when the answer
// has been determined to be incorrect.
public void wrongAnswer(String answer) {
wrongAnswers.add(answer);
}
public void printWrongAnswers() {
System.out.println("Wrong answers:");
for (String answer : wrongAnswers) {
System.out.println(answer);
}
}
Start with an ArrayList and then you can call toArray() to get an actual array.
You can also initialize an array whose size is the number of questions you have. Then keep a running count of missed questions, and simply trim the array at the end.
Look into using an ArrayList. This is an implementation of the List interface that is backed by an array.
Using the default constructor, it will start with a backing array of size 10 (but don't worry too much about this detail):
List<Question> questionList = new ArrayList<Question>();
You can then add elements:
questionList.add(question);
It will then resize this array as needed as you continue to add elements.
Since you probably know how many questions you are going to ask, you can stick to the array if you like and make it exactly as long as the number of questions you have. I would like to see the first person who succeeds in answering more questions incorrect then the number of questions available on the test
Use a collection, like a List implementation (like ArrayList), instead of an array. Then you can add by calling list.add(miss) and never worry about the size.
Do you specifically need an array? You can get the array, but in general, it's rare to specifically need one for requirements like these.

How to cast an array to an array with another primitive type

Can someone complete the code on an easy way?
float[] floats = {...}; // create an array
// Now I want to create a new array of ints from the arrays floats
int[] ints = ????;
I know I can simply cast element by element to a new array. But is it possible on an easier way?
Thanks
I'm pretty sure you can't do it any other way for your float to int example than individually casting each and every element.
I quickly Googled this which turned up somebody with a similar problem that more or less corroborates what I've said:
http://www.java-forums.org/advanced-java/11255-type-casting-array.html
I would recommend just individually casting the elements. It's guaranteed to work and be easy to understand for a future developer. Any sort of "cast all at once" code would probably just be doing that behind the scenes anyway.
You cannot do this directly. Based on the context of how this array is created in used, you may want to consider using an array of a wrapper class, where your setter accepts a float and getter returns an int.
This would be ideal, if it is practical in your situation, because you get to hide the conversion from the client code.

Categories