views:

375

answers:

6

If you have an instance of a Collection, say something like:

Collection<String> addresses = new ArrayList<String>();

Which were to then be populated with a bunch of values, which is the "best" way, if any, to make use of the toArray() method without requiring a type cast?

String[] addressesArray = addresses.toArray(new String[] {});
String[] addressesArray = addresses.toArray(new String[0]);
String[] addressesArray = addresses.toArray(new String[addresses.size()]);
String[] addressesArray = addresses.toArray(new String[addresses.size() + 5]);

Is there any semantic difference between the first two? Is the third most efficient? Is the fourth less efficient than the third?

A: 

This is documented in javadoc of the List interface:

If the list fits in the specified array with room to spare (i.e., the array has more elements than the list), the element in the array immediately following the end of the list is set to null. (This is useful in determining the length of the list only if the caller knows that the list does not contain any null elements.)

andri
It makes sense that if the size of the ArrayList is 5, and you pass toArray() a new String array of size 10 then it would be resized, but I still don't know which is more or less proper/efficient.
craig
It does not resize the array, it simply sets the element past the end of the list to null.
Grant Wagner
+5  A: 

According to a findbugs report, this is the most efficient:

String[] addressesArray = addresses.toArray(new String[addresses.size()]);

I believe them ;)

Marcelo Morales
A: 

You're doing effectively the same thing with the first two statements.

The third is most efficient, for if your elements will not fit into the array, a new array is created for you.

Steve Reed
+3  A: 

If you choose not to believe others, or just want to check for yourself, you can review the source for java.util.ArrayList (posting the source probably violates some license, I'm glad I'm just linking to it). You also get a copy of all the source code when you download Sun's JDK).

After reviewing the source code for <T> T[] toArray(T[] a); it is apparent that:

String[] addressesArray = addresses.toArray(new String[addresses.size()]);

is the fastest way to do it.

Obviously you can't always take the time to read and understand the source code, and sometimes the best performing option is not always obvious, but for simpler methods, it can be very informative to read the source.

Grant Wagner
+1  A: 

For my money

String[] addressesArray = addresses.toArray(new String[0]);

is simplest, least error-prone and therefore "best". It also has the advantage that the same code works for concurrent/synchronized collections. You would have to be in some really low-level, heavily used code for the negligible performance difference to make any difference.

Often you see an empty array assigned to a static final to avoid the allocation on every execution. Apparently, it turns out that the performance can drop due to that "optimisation" (allocation really are very fast).

Tom Hawtin - tackline
+1 for noticing the concurrency issue. I've faced that issue in my code once: http://github.com/orfjackal/dimdwarf/blob/0d1a0897821a4e0e557a1390a7252a8580d2ec95/dimdwarf-core/src/main/java/net/orfjackal/dimdwarf/scheduler/TaskThreadPool.java#L111-116
Esko Luontola
Though normally I use the "addresses.toArray(new String[addresses.size()])" approach.
Esko Luontola
A: 

This is mostly of theoretical interest, but if the list is empty often, you can reuse a zero-length array:

private static final String[] EMPTY_STRING_ARRAY = {};
...
String[] addressesArray = addresses.toArray(EMPTY_STRING_ARRAY);

Since zero-length arrays are immutable (unlike non-zero-length arrays), they are OK to store away and reuse.

gustafc
See Tom Hawtin's answer.
Michael Myers