Reputation: 3051
What is the better way to convert List to varargs to call below 'builder( String... s )' method.
builder( stringList.toArray( new String[stringList.size()] ) );//with pre-defined array size
or
builder( stringList.toArray( new String[0] ) );//without predefined size
For example
void test() {
List<String> stringList = new ArrayList<>();
builder( stringList.toArray( new String[stringList.size()] ) );//call builder method with pre-difining array size
builder( stringList.toArray( new String[0] ) );//call builder method with array size 0
}
void builder( String... s )
{
}
I faced this question in a review and I was suggested that builder(stringList.toArray(new String[0]))
is more efficient than
using builder(stringList.toArray(new String[stringList.size()]))
.
Is there a significant difference between these two?
Thanks
Upvotes: 3
Views: 622
Reputation: 109577
To my understanding
stringList.toArray( new String[stringList.size()] ) )
is more efficient. The reason:
The argument is needed to have an actual type (String
) for a generic List<String>
, where the generic type parameter is erased at run-time.
The argument is used for the resulting array if its size matches the list size.
If the size is 0, the passed array is discarded.
So passing a correct array saves one object creation.
Of course list.size()
is called extra. So it might be slower. I doubt it.
Correction
See Arrays of Wisdom of the Ancients.
A correct benchmark shows the inverse: new String[0]
being faster.
I just overflew the very interesting analysis, and it seems:
new String[0]
is irrelevant;)size
.)Mind, I did not sufficiently thorough read the article; it really is interesting.
Conclusion (counter-intuitively): new T[0]
is faster.
Mind that:
Upvotes: 5
Reputation: 120938
There is a difference and it's mainly outlined by the Alexey Shipilev. Long story short:
toArray(new T[0]) seems faster, safer, and contractually cleaner, and therefore should be the default choice now
Upvotes: 2
Reputation: 18245
I thought that c.toArray(new String[c.size()]))
is more efficient, because we define here an array with required size.
BUT!!
IntelliJ IDEA has Collection.toArray() inspection, which is on by default. This is description:
There are two styles to convert a collection to an array: either using a pre-sized array (like c.toArray(new String[c.size()])) or using an empty array (like c.toArray(new String[0]).
In older Java versions using pre-sized array was recommended, as the reflection call which is necessary to create an array of proper size was quite slow. However since late updates of OpenJDK 6 this call was intrinsified, making the performance of the empty array version the same and sometimes even better, compared to the pre-sized version. Also passing pre-sized array is dangerous for a concurrent or synchronized collection as a data race is possible between the size and toArray call which may result in extra nulls at the end of the array, if the collection was concurrently shrunk during the operation.
This inspection allows to follow the uniform style: either using an empty array (which is recommended in modern Java) or using a pre-sized array (which might be faster in older Java versions or non-HotSpot based JVMs).
So it seems, that after JDK6, we should use c.toArray(new String[0])
. My personal opinion, is that it doesn't matter what aporoach to use this time. Only if profiler says that this is a bottle neck, then we should worry about it.
Upvotes: 1
Reputation: 393886
builder(stringList.toArray(new String[0]))
is slightly less efficient since you create an empty array that will be discarded and never used after the method returns. toArray
will have to create a new array in order to store the elements of the List
.
On the other hand, builder(stringList.toArray(new String[stringList.size()]))
passes an array of the required length to the toArray
method, and therefore that method will use that array instead of creating a new array.
Upvotes: 2