The easiest way to transform collection to array?

Viewed 197711

Suppose we have a Collection<Foo>. What is the best (shortest in LoC in current context) way to transform it to Foo[]? Any well-known libraries are allowed.

UPD: (one more case in this section; leave comments if you think it's worth to create another thread for it): What about transforming Collection<Foo> to Bar[] where Bar has constructor with 1 parameter of type Foo i.e. public Bar(Foo foo){ ... } ?

10 Answers

Alternative solution to the updated question using Java 8:

Bar[] result = foos.stream()
    .map(x -> new Bar(x))
    .toArray(size -> new Bar[size]);

With JDK/11, an alternate way of converting a Collection<Foo> to an Foo[] could be to make use of Collection.toArray(IntFunction<T[]> generator) as:

Foo[] foos = fooCollection.toArray(new Foo[0]); // before JDK 11
Foo[] updatedFoos = fooCollection.toArray(Foo[]::new); // after JDK 11

As explained by @Stuart on the mailing list(emphasis mine), the performance of this should essentially be the same as that of the existing Collection.toArray(new T[0]) --

The upshot is that implementations that use Arrays.copyOf() are the fastest, probably because it's an intrinsic.

It can avoid zero-filling the freshly allocated array because it knows the entire array contents will be overwritten. This is true regardless of what the public API looks like.

The implementation of the API within the JDK reads:

default <T> T[] toArray(IntFunction<T[]> generator) {
    return toArray(generator.apply(0));
}

The default implementation calls generator.apply(0) to get a zero-length array and then simply calls toArray(T[]). This goes through the Arrays.copyOf() fast path, so it's essentially the same speed as toArray(new T[0]).


Note:- Just that the API use shall be guided along with a backward incompatibility when used for code with null values e.g. toArray(null) since these calls would now be ambiguous because of existing toArray(T[] a) and would fail to compile.

If you use Guava in your project you can use Iterables::toArray.

Foo[] foos = Iterables.toArray(x, Foo.class);

Actually in modern Java, the version without setting the explicit size is faster. See this SO answer:

.toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?

This is backed up by independent research and the team at IntelliJ.

That is, this is the fastest approach today:

Foo[] foos = x.toArray(new Foo[0])

Or, even better, with a bit of safety:

Foo[] foos = x == null ? null : x.toArray(new Foo[0])

Foo[] foos = x.toArray(new Foo[0]);

For example, you have collection ArrayList with elements Student class:

List stuList = new ArrayList();
Student s1 = new Student("Raju");
Student s2 = new Student("Harish");
stuList.add(s1);
stuList.add(s2);
//now you can convert this collection stuList to Array like this
Object[] stuArr = stuList.toArray();           // <----- toArray() function will convert collection to array
Related