Performance Tip: avoid Collection.toArray(new Type[0])

Overview

The Collection.toArray(Object[]) can be used in a number of ways. Depending on how big you expect the collection to be, one of three approaches can be a better solution. A four option Collection.toArray(new Type[0]) should be avoided.

Create an empty array constant

A pre-built String[] is used to pass as an argument. This is most efficient when the array usually has a size of 0. If the size is greater than 0, an extra reflective call is required.

From AbstractPreferences.childNames():
// ends with
return (String[]) s.toArray(EMPTY_STRING_ARRAY);
}

private static final String[] EMPTY_STRING_ARRAY = new String[0];
Generally its safe to assume all zero length array of a given type are the same. i.e. they are immutable. Arrays can be used for locks, but this is rare and bad practice (esp. to use the result of a method like this as a lock)

Create an array of the correct size.

This avoids a reflective call, but results in creating an array every time (even for zero length arrays)

From File.list(FilenameFilter)
return (String[])(v.toArray(new String[v.size()]));
This is most efficient for sizes > 0.

This is also the shortest/simplest option, making it the best in most cases.

Don't: Create a zero length array every time

This approach is the worst of both worlds. You get the cost of the first example and the cost of the second example. It is never a good idea.

From javax.management.timer.Timer.getNotificationInfo()
String[] notifTypesArray =
            notifTypes.toArray(new String[0]);
This will create a one or two arrays and possibly a reflective call. It is best not to use this option.

The best of both worlds

The fastest option, if the size can be zero, is to use the best of the first two options. I couldn't find example in the JDK but it looks like this.

return s.isEmpty ? EMPTY_STRING_ARRAY : (String[]) s.toArray(new String[a.size()]);

private static final String[] EMPTY_STRING_ARRAY = new String[0];
This way an empty array is reused whenever there are no results and extract the right size and type is used when the size() >= 1.

Comments

Popular posts from this blog

Low Latency Microservices, A Retrospective

Unusual Java: StackTrace Extends Throwable

System wide unique nanosecond timestamps