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 10
Where x
is the collection:
Foo[] foos = x.toArray(new Foo[x.size()]);
9 Comments
x.toArray(new Foo[0])
--- documentation: no time to read...(new Foo[0])
. As per the Collection.toArray documentation, ` @param a the array into which the elements of this collection are to be stored, if it is big enough` which means it will store them directly in that new array. If you give it a size 0 array, it will make a new array, meaning you have a small array and a large array being made when such is unnecessary.toArray
to create a target array of the correct type. And in this case, honestly, I wouldn't care about one extra single empty array in my application. That's far below noise level.new Foo[0]
is simpler "but not best (memory)"... that is, I meant that my solution is easier but not best (that's the reason I used :
).new Foo[0]
variant proposed by Carlos does not suffer this problem.Alternative solution to the updated question using Java 8:
Bar[] result = foos.stream()
.map(x -> new Bar(x))
.toArray(size -> new Bar[size]);
3 Comments
Bar[] result = foos.stream().map(Bar::new).toArray(Bar[]::new);
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[]{});
5 Comments
const
is not Java! public static final Foo[] FOO = {}
import static
to get at them.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 callstoArray(T[])
. This goes through theArrays.copyOf()
fast path, so it's essentially the same speed astoArray(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.
Comments
If you use Guava in your project you can use Iterables::toArray
.
Foo[] foos = Iterables.toArray(x, Foo.class);
Comments
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).
1 Comment
new Bar[0]
avoids the issue.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);
}
Comments
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])
Comments
Foo[] foos = x.toArray(new Foo[0]);
Comments
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
Comments
Explore related questions
See similar questions with these tags.
Stream.toArray
API from the JDK.