The easiest way to transform collection to array?
JavaArraysCollectionsTransformationJava Problem Overview
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){ ... }
?
Java Solutions
Solution 1 - Java
Where x
is the collection:
Foo[] foos = x.toArray(new Foo[x.size()]);
Solution 2 - Java
Alternative solution to the updated question using Java 8:
Bar[] result = foos.stream()
.map(x -> new Bar(x))
.toArray(size -> new Bar[size]);
Solution 3 - Java
If you use it more than once or in a loop, you could define a constant
public static final Foo[] FOO = new Foo[]{};
and do the conversion it like
Foo[] foos = fooCollection.toArray(FOO);
The toArray
method will take the empty array to determine the correct type of the target array and create a new array for you.
Here's my proposal for the update:
Collection<Foo> foos = new ArrayList<Foo>();
Collection<Bar> temp = new ArrayList<Bar>();
for (Foo foo:foos)
temp.add(new Bar(foo));
Bar[] bars = temp.toArray(new Bar[]{});
Solution 4 - Java
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.
Solution 5 - Java
If you use Guava in your project you can use Iterables::toArray
.
Foo[] foos = Iterables.toArray(x, Foo.class);
Solution 6 - Java
Here's the final solution for the case in update section (with the help of Google Collections):
Collections2.transform (fooCollection, new Function<Foo, Bar>() {
public Bar apply (Foo foo) {
return new Bar (foo);
}
}).toArray (new Bar[fooCollection.size()]);
But, the key approach here was mentioned in the doublep's answer (I forgot for toArray
method).
Solution 7 - Java
For the original see doublep answer:
Foo[] a = x.toArray(new Foo[x.size()]);
As for the update:
int i = 0;
Bar[] bars = new Bar[fooCollection.size()];
for( Foo foo : fooCollection ) { // where fooCollection is Collection<Foo>
bars[i++] = new Bar(foo);
}
Solution 8 - Java
Actually in modern Java, the version without setting the explicit size is faster. See this SO answer:
https://stackoverflow.com/questions/174093/toarraynew-myclass0-or-toarraynew-myclassmylist-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])
Solution 9 - Java
Foo[] foos = x.toArray(new Foo[0]);
Solution 10 - Java
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