Could someone show me a practical a use of the ... array method delcaration?
Is it just a way to declare an optional parameter instead of passing null value?
public void add(int a, int... b) {
// do something
}
add(1);
add(1,2,3);
String.format is a pretty good practical example. The method doesn't know how many formatters will appear in the format string, so it accepts a variable number of arguments, and there should be a one-to-one mapping of formatters (in the format string) to objects passed into the method.
It's not so much a way of declaring an option parameter rather than null, as it is to declare a method that can deal with multiple arguments. Basing my example off of mine, you could write a sum method that takes a variable number of arguments and sums them all together:
public int sum(int... ns)
{
int sum = 0;
for (int n : ns) {
sum += n;
}
return sum;
}
That way, you could pass in 2, 3, 4, or even 100 numbers to sum, depending on your need at the time.
It's a shorthand for you when you're writing code that will use a function that can take an array as a parameter.
It's generally easier to write add(1,2,3,4); than it is to write add(new int[] {1,2,3,4});, right? It's also clearer when it needs to be read and maintained by future programmers later.
Think about it this way: which function would you call, the one where you have to create an array every time, or the one where you can just pass in as many parameters as you want?
The Formatter class is such a practical use:
Formatter formatter = new Formatter(sb, Locale.US);
formatter.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d")
An arbitrary number of parameters can be passed in to be formatted using the first parameter, which is the format string itself.
Before varargs a method that took an arbitrary number of values required you to create an array put the values into the array prior to invoking the method. Example here is how the MessageFormat class to format a message used to look:
Object[] arguments = {
new Integer(7),
new Date(),
"a disturbance in the Force"
};
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet "
+ "{0,number,integer}.", arguments);
It is still true that multiple arguments must be passed in an array, but the varargs feature automates and hides the process. Furthermore, it is upward compatible with preexisting APIs. So, for example, the MessageFormat.format method now has this declaration:
public static String format(String pattern,
Object... arguments);
The three periods after the final parameter's type indicate that the final argument may be passed as an array or as a sequence of arguments. Varargs can be used only in the final argument position. Given the new varargs declaration for MessageFormat.format, the above invocation may be replaced by the following shorter and sweeter invocation:
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet "
+ "{0,number,integer}.",
7, new Date(), "a disturbance in the Force");
So when should you use varargs? As a client, you should take advantage of them whenever the API offers them. Important uses in core APIs include reflection, message formatting, and the new printf facility. As an API designer, you should use them sparingly, only when the benefit is truly compelling. Generally speaking, you should not overload a varargs method, or it will be difficult for programmers to figure out which overloading gets called.
From: http://java.sun.com/j2se/1.5.0/docs/guide/language/varargs.html
Derived from you example you could make a method to have the sum of all the ints you pass to the method:
public int sum(int a, int... b) {
int sum = a;
for (int i : b) {
sum += i;
}
return sum;
}
Related
Assuming I have a list of 100 strings. Is there a difference between the following two approaches in performance (or any other difference)
1.
List<String> myList = Arrays.asList("s1", "s2", "s3"....."s100");
foo(myList);
private void foo(List<String> myList) {
// logic to choose 2 strings from the list
//do something with -- str1 and str2
}
2.
List<String> myList = Arrays.asList("s1", "s2", "s3"....."s100");
// logic to choose 2 strings from the list
foo(str1, str2);
private void foo(String myStr1, String myStr2) {
//do something with -- myStr1 and myStr2
}
Since Java passes the reference(as values) of the List or individual Strings I am assuming those arguments will just hold (copies of) references/addresses. So I am leaning towards passing the entire list.
The above will be a utility method and I want to put the 'logic to choose 2 strings from the list' inside the foo method so callers don't have to repeat that logic before calling; but I am concerned about sending a large list as argument.
Thanks for help.
** Edit :**
Yes I am looking for Performance concerns.
And List<String> probably wasn't the correct example. Think of it as a Map<String,Long> (City,Temperature). And the logic will be to always choose Chicago and LA and foo will operate on the temperatures. Note that this logic will always be the same and callers would just repeat the same code in approach #2.
I recommend you ignore potential difference in performance (which would be negligible in this case) and focus entirely on clarity of your code. In other words, the question is not which is more efficient but which better reflects the intention of the method you are calling. If foo is a method which would naturally expect two arguments (such as storeFullName) then it should be passed two arguments. If it would naturally expect to select two values from a list (such as printTwoLongestStrings) then it should take a collection.
You might also consider the principle of giving each method a single responsibility. In that case it might make sense to have separate methods for selecting the two values and doing something with them:
Pair<String, String> longestPair = getTwoLongestStrings(list);
printStrings(longestPair);
** Edit **
Your question has clarified that you are focused specifically on performance and you provided more detail of your use case. Specifically you are asking if there is a difference in performance in passing a list or two values to a method. Yes there is a difference. I ran a trial calling an empty function 10 billion times with two String arguments and with a list. The list call took 24 secs and the separate argument call took 13 secs. It's likely that other physical hardware will show different results. It's also possible that JVM optimisation is not making this a fair test.
public class PerfTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b");
long time1 = System.currentTimeMillis();
for (long i = 0; i < 1E10; i++) {
func1("a", "b");
}
long time2 = System.currentTimeMillis();
for (long i = 0; i < 1E10; i++) {
func2(list);
}
System.out.println((time2 - time1) + "/" + (System.currentTimeMillis() - time2));
}
private static void func1(String s1, String s2) { }
private static void func2(List<String> sl) { }
}
However my answer above still stands: if you are calling a function 10 billion times then it might be worth optimising but it is much better practice to start with a focus on clarity and then use profiling to focus code-tuning effort if that is required.
I think you are asking if a List argument is passed by reference. It is. In the compiled machine code, for the list argument just a single pointer to the list object instance will be passed to the function. There is no reason to be concerned about having a large list as an argument.
I recommend only using a List as an argument if the method is interested in the list itself and not only its items, e.g. it plans on modifying it.
For the other cases, if you have a fixed number of arguments, you should have each argument be it's own parameter. But your case suggested that you have a variable number of arguments. For this you could also use varargs:
private void foo(String... strings) {
// `strings` is an array now
}
This has the advantage that the caller can choose to either invoke your function using single objects, or an array:
foo("Hello", "World");
or this
String[] strings = new String[]{"Hello", "World"};
foo(strings);
or even this:
List<String> strings = ...;
foo(strings.toArray(new String[0]));
If you have concerns about turning your list into an array, stick with passing the list itself.
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
What does “…” mean in Java?
Java array argument “declaration” syntax
Can anyone confirm if I'm right in seeing the Object... parameter in the method call below:
public static void setValues(PreparedStatement preparedStatement, Object... values)
throws SQLException
{
for (int i = 0; i < values.length; i++) {
preparedStatement.setObject(i + 1, values[i]);
}
}
As an array of type Object? I don't recall seeing ... before in Java.
It's equivalent to Object[], but allows the caller to just specify the values one at a time as arguments, and the compiler will create an array. So this call:
setValues(statement, arg1, arg2, arg3);
is equivalent to
setValues(statement, new Object[] { arg1, arg2, arg3 });
See the documentation for the varargs feature (introduced in Java 5) for more information.
From the Java Tutorial (Passing Information to a Method or Constructor):
Arbitrary Number of Arguments
You can use a construct called varargs
to pass an arbitrary number of values
to a method. You use varargs when you
don't know how many of a particular
type of argument will be passed to the
method. It's a shortcut to creating an
array manually (the previous method
could have used varargs rather than an
array). To use varargs, you follow the
type of the last parameter by an
ellipsis (three dots, ...), then a
space, and the parameter name. The
method can then be called with any
number of that parameter, including
none.
public Polygon polygonFrom(Point... corners) {
int numberOfSides = corners.length;
double squareOfSide1, lengthOfSide1;
squareOfSide1 = (corners[1].x - corners[0].x)*(corners[1].x - corners[0].x)
+ (corners[1].y - corners[0].y)*(corners[1].y - corners[0].y) ;
lengthOfSide1 = Math.sqrt(squareOfSide1);
// more method body code follows that creates
// and returns a polygon connecting the Points
}
You can see
that, inside the method, corners is
treated like an array. The method can
be called either with an array or with
a sequence of arguments. The code in
the method body will treat the
parameter as an array in either case.
What you are looking at is a varargs parameter. The documentation on it can be found here.
Varargs are equivalent to an object array, but there is syntactic sugar to make calling that method easier. So the old way was (this code is from the document above):
Object[] arguments = {
new Integer(7),
new Date(),
"a disturbance in the Force"
};
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet "
+ "{0,number,integer}.", arguments);
With varargs you get to write:
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet "
+ "{0,number,integer}.", 7, new Date(), "a disturbance in the Force");
Note that autoboxing helps here to convert the int 7 to new Integer(7) without you having to explicitly declare it.
This is my code:
public class Test
{
public static void main(String arg[]) {
new Test().method1(5);
}
public void method1(int b) { // integer method
System.out.println("integer ");
}
public void method1(short a) { // short method
System.out.println("short");
}
}
I am running this class, and it gives me result of integer. Why it is not giving short?
Because the literal 5 is by default understood as an int. If you want to call the method1(short a) method, you need to explicitly do a cast:
new Test().method1((short) 5);
The literal 5 has type int, that's why the method that expects an int is called.
new Test().method1((short)5) would call the method that expects a short.
Default type of Java integer literals is int thats why integer method is getting invoked.
you have to apply type conversion because you are willing to call a function which receives short.
try calling with:(short)5
It's because, as noted in the other answers, a 5 on its own denotes an int. You can denote a long by appending an L, so 5L would be treated as a long. If you want a byte or a short then you have to cast explicitly.
It may be that you have a good reason for wanting a method that takes a short, but please bear in mind that this is quite rare. Certainly you would not want to be doing this for performance reasons. Java uses a 32-bit int by default because pretty much every processor out there can work natively with 32-bit integers. You will probably find that a short will operate more slowly than an int.
(Of course, if you're doing specifically 16-bit arithmetic, then you might still need to use a short.)
I need to pass arguments to a java method func(String, String...).
Problem is I have all the strings I need to pass as arguments, but they are in an ArrayList container.
For Example:
for(...some condition...)
{
//the other method returns an ArrayList with different size in each iteration
ArrayList <String> values = someOtherMethod();
func(values) //values is an ArrayList<String>, containing all the arguments
}
I get an error saying that ArrayList<String> can't be converted to String.
The size of values changes, because the someOtherMethod method returns a container with different size each iteration, so I can't pass values[0], values[1], etc as arguments.
I'm guessing the func wants an X amount of String variables, but I don't know how to convert a container to an X amount of variables when the size of the container isn't constant.
The "..." operator accepts arrays, so you could just do the following:
ArrayList <String> values = someOtherMethod();
func(values.toArray(new String[values.size()]);
It's a little bit complex as func requires one String and then an arbitrary number of additional Strings:
List<String> values = someOtherMethod();
if (values.isEmpty()) {
// handle special case
} else{
func(values.get(0), values.subList(1, values.size()).toArray(new String[]));
}
I'm guessing the func wants an X amount of String variables,
I guess you are looking for Varargs.
Change your function signature to accept as
public someReturnType func(String... vargs) { }
Which takes variable length of args as parameter.
And then inside the method ,you can access them like
for (String currentarg: args) {
// do something with currentarg
}
As a side note : Available from version 1.5 only.
Learn more from docs about Varargs
I'm a beginner in Java programming, and I'm trying to make a voting machine program, where you can vote for Republicans or Democrats. My question is, how can I edit my method so I would be able to return two strings with two distinct values?
For example, look at my code all the way in the bottom. It's wrong, but I wanted the tester to be able to print out Democrats: (some number) and Republicans: (some number) in one method. How can I do that?
import java.lang.String;
public class VotingMachine1 {
private double Democrats;
private double Republicans;
public VotingMachine1() {
Democrats = 0;
Republicans = 0;
}
public void voteRepublican() {
Republicans = Republicans + 1;
}
public void voteDemocrat() {
Democrats = Democrats + 1;
}
public void clearMachineState() {
Republicans = 0;
Democrats = 0;
}
//this is where I'm having difficulties. I know its wrong
public double getTallies() {
System.out.println("Democrats: ", return Democrats);
System.out.println("Republicans: ", return Republicans);
}
}
No return is necessary there, since you aren't leaving a function. To do what you seem to want to do, just replace that last method with the following:
public void getTallies()
{
System.out.println("Democrats: " + Double.toString(Democrats));
System.out.println("Republicans: " + Double.toString(Republicans));
}
Also, since your votecounts should only ever be integers, there's no reason to declare them as doubles instead of ints.
What you are looking for here is a format string. A format string is used when you know what your output should look like, and only have a few "holes" where unknown data should be filled in. To output your data using format strings, you would use the System.out.format(String, Object...) method:
System.out.format("Democrats: %f\n", Democrats);
System.out.format("Republicans: %f\n", Republicans);
In this case, the %f indicates that a floating-point number (since your variables are declared as double) will be printed instead of the %f. However, you may wish to consider declaring them as int (or long) instead, in which case you would use %d instead of %f in the format strings.
Finally, you ought to change your getTallies() method to return void instead of double, as you are printing the values, not returning them.
Your code and your description are so contradictory, it is not clear that you even know what you are trying to do. I believe that this is the real root of your problems.
Here goes:
public double getTallies()
{
System.out.println("Democrats: ", return Democrats);
System.out.println("Republicans: ", return Republicans);
}
First, your question says that you want to "return two strings with two values" ... but you have declared the method as returning one double.
Next, your code is printing values ... not returning them.
You've also made some major mistakes at the syntactic level, largely (I believe) because you are trying to do contradictory things:
return Republicans is not a valid Java expression, so you can't use it as a argument to the println method.
The println method can't be called with two arguments, as your code is trying to do. There is a zero argument version and a number of one argument overloads ... but no overloads with two or more arguments.
Basically, you need to start by making up your mind about what this method is supposed to do. Is it supposed to:
return the tallies (as two doubles)?
return a string representing the two tallies?
return nothing ... and output the two tallies to standard output?
do something else?
Once you've made up your mind:
code the method to do what you've decided it should do, and
chose a method name that correctly reflects what it is supposed to do. Hint: a method that starts with get is conventionally a "getter" that returns the attribute or attributes themselves ... not a String rendering.
double is a bad choice of type for a vote count too:
You cannot have a fractional vote.
You want to represent vote counts precisely and floating point types (like double) are not precise. (Or at least, not in the sense that you require.)
When you attempt to format or output a double, the resulting character string is likely to include a pesky decimal point ... or worse.
You should use int or long instead of double.
Finally, this is a serious Java style violation, and should get you a significant penalty if your marker is paying attention.
private double Democrats;
private double Republicans;
Variable names in Java should start with a LOWER CASE letter.
A few more random comments:
import java.lang.String; is superfluous as all classes in package java.lang are automatically imported in every Java source file.
Votes can not be fractional. People can't vote 0.75 candidate A, and 0.25 candidate B. If you use integer datatypes (int or long), you will be reflecting this fact better. Also, you will be saving yourself a lot of headache when you start obtaining results like 379857.999999. This is because floating point types have a better range, but worse precision (especially noticeable when working with pure integers).
According to Java usual naming conventions, variable names should start with a lowecase letter.
A better name for function getTallies is printTallies.
For output purposes, it's much better to use string formatting than concatenation. Some advantages are: multiple formats supported, ease of use, and internationalization.
Putting all together:
private int democratVotes;
private int republicanVotes;
public void printTallies() {
System.out.format("Democrats: %,d%n",democratVotes);
System.out.format("Republicans: %,d%n",republicanVotes);
}
In this particular case, votes will be printed with thousand separation (ex: 3,345,623 instead of 3345623). Check Java's Formatting Numeric Print Output tutorial.
Thinking better about it, there are some alternatives where getTallies would effectively be returning some form of value:
1) Make it to return a String with both tallies. It would be hard and inefficient to separate the tallies later, though.
public String getTallies() {
return "Democrats: %,d votes. Republicans: %,d votes.%n".format(democratVotes,republicanVotes);
}
2) Make it to return an array.
public int[] getTallies() {
return new int[2]{ democratVotes, republicanVotes };
}
public int[] getTallies1() { // Same as getTallies, but written step by step.
int[] result= new int[2] ;
result[0]= democratVotes ;
result[1]= republicanVotes ;
return result ;
}
3) Make it to return a class.
public VotingMachineResults getTallies() {
return VotingMachineResults(democratVotes,republicanVotes) ;
}
public static class VotingMachineResults {
private int democratVotes;
private int republicanVotes;
public VotingMachineResults(democratVotes,republicanVotes) {
this.democratVotes= democratVotes ; // `this` required to disambiguate field democratVotes from parameter democratVotes.
this.republicanVotes= republicanVotes ;
}
public int getDemocratVotes() {
return democratVotes ;
}
public int getRepublicanVotes() {
return republicanVotes ;
}
}
As you can see, this class is very similar to VotingMachine1, but it does not accept internal state changes. It is a "value" class.
In Java, you concatenate Strings with the + operator. Proper syntax for what you were trying to do looks like this:
System.out.println("Democrats: " + Democrats);
System.out.println("Republicans: " + Republicans);
A return statement is only used when you want to return some object or value to a method that called your current method. It is not appropriate in this place since you're only passing a value to another method (println()).
ALSO, you need to fix your getTallies() method. Make it return void instead of double since you aren't returning anything.
Here's something completely different: why not override toString()?
Presumably, any instance of VotingMachine1 will apply for all votes that you care about for that instance. That is to say, you don't create a new instance of a VotingMachine1 every time someone casts a vote.
So, what you can do is override the toString() method. We'll also use String.format() to handle the numerical values.
#Override
public String toString() {
// assumes that Democrats and Republicans are declared as int
// since it's pointless to indicate percentages of a vote
return String.format("Democrats: %d\nRepublicans: %d", Democrats, Republicans);
}
Now, whenever you vote, you can use the toString() method to get the information (which is called whenever one does System.out.println(object).
VotingMachine1 voter = new VotingMachine1();
voter.voteDemocrat();
voter.voteRepublican();
System.out.println(voter);
/* This prints:
Democrats: 1
Republicans: 1
*/
A less specific answer to your question would be to return an Object called (say) Votes
public class Vote {
int democratVotes
int republicanVotes
}
and then make your VotingMachine class simply return an instance of this object (suitably changed to make it immutable).
On my project we have created a generic version of this called a Tuple that returns a pair of values in a single object - it has an overloaded toString method for easy printing.
you can return an array with [0] and [1] as key and devide it on the basis of your need..
like
returnArray[0]="first string";
returnArray[1]="second string";
and use it ur way...