Reputation: 388
I am converting an ArrayList to an Array using
ArrayList<String> var1 = new ArrayList<>();
for(condition){
// Add items to var1
}
return var1.toArray(new String[]{})
My IDE is recommending i change the last line to
return var1.toArray(String[]::new)
Is this just better convention or is there also some benefits to compile-time or memory usage.
Upvotes: 1
Views: 879
Reputation: 103893
String[]::new
is a function. It does not create a new string array, it defines a function that makes new string arrays. It's like the difference between a cake, and a recipe to make a cake. One consists of flour and icing and all that. The other one is just words and paper. Completely different things, but related, in that the recipe lets you make cake (any number of them, even!)
String[]::new
is shorthand* for:
public String[] makeNewStringArray(int size) {
return new String[size];
}
Merely writing that doesn't make any string arrays at all; calling that function would make one string array each time it is invoked.
Example:
IntFunction<String[]> stringArrayMaker = String[]::new;
String[] size10 = stringArrayMaker.apply(10);
What you've written is slightly non-standard; new String[0]
is more standard. So let's compare new String[0]
versus String[]::new
.
The only point of this parameter is to allow the arraylist to know what type you want. You'd think the arraylist already knows (it is an ArrayList<String>
after all!) but due to generics erasure (a rather complex topic), there is no way for the code of toArray
to know what you want, therefore, you must specify.
new String[0]
ends up making a 0-length string array which is then immediately discarded. This feels wasteful, but garbage collection being what it is, 'quick garbage' (objects made and discarded very quickly and never shared with other threads) is almost entirely free. This method (toArray(T[])
) works as follows: If the incoming array is as large or larger than is needed, it is filled, and returned. If it is too small, a new array is created with the same component type of the right size, that one is filled, and that one is returned.
You'd think, therefore, that var1.toArray(new String[var1.size()])
is the most efficient. But JMH tells me there is no difference at all. Which goes to show how incredibly efficient java is at dealing with short lived garbage (when I say 'short lived garbage is free', I mean it. It's almost impossible to witness the cost of it).
The functional approach (where you pass String[]::new
) means that this function will take care of making the array, and toArray
itself just relies on what it gets. This.. also works fine. It ends up making a method in your class file someplace.
So, it really doesn't matter. I find the IDE being overly preachy here. String[]::new
makes a new method, and the overhead in class space alone probably means it ends up being less efficient, even though the creation of the garbage is more easily understandable inefficiency.
But, we're really nitpicking here. Literally talking about nanoseconds - you're never going to notice.
Do whatever you find is most readable (though I would steer clear of new String[]{}
- nothing wrong with it perse, but it's not very common and it has no benefits over new String[0]
- might as well do what the community does if it doesn't otherwise matter).
*) This is slightly oversimplified, but not by much.
Upvotes: 8
Reputation: 141
"String[]::new" is a method reference. Its basically the same as "new String[]". See Method References for more detail.
Upvotes: -6