147

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){ ... } ?

asked Jul 20, 2010 at 20:10
1
  • 1
    Made this answer with an alternate API introduced in JDK-11 to perform the same operation with similar performance and the explanation along with it. Plus the syntax matches the existing Stream.toArray API from the JDK. Commented Jul 26, 2018 at 18:59

10 Answers 10

282

Where x is the collection:

Foo[] foos = x.toArray(new Foo[x.size()]);
Auroratic
4728 silver badges26 bronze badges
answered Jul 20, 2010 at 20:13
Sign up to request clarification or add additional context in comments.

9 Comments

simpler (easier) but not best(memory): x.toArray(new Foo[0]) --- documentation: no time to read...
@Carlos actually, it uses better memory than (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.
@glowcoder - but this can be minimized if you define a empty array once as a static constant. It's just a hint for 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.
@glowcoder - that's exactly why I (tried to) wrote that using 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 : ).
Note that this code is not threadsafe, even if you're using a synchronized collection. It'll behave itself in most situations, but if an item is deleted between the call to x.size() and x.toArray(), the resulting array will contain an extra null element at the end. The new Foo[0] variant proposed by Carlos does not suffer this problem.
|
44

Alternative solution to the updated question using Java 8:

Bar[] result = foos.stream()
 .map(x -> new Bar(x))
 .toArray(size -> new Bar[size]);
answered Nov 19, 2013 at 2:42

3 Comments

This can be shortened to Bar[] result = foos.stream().map(Bar::new).toArray(Bar[]::new);
Syntax wise I'd much prefer the accepted answer. I wish people can all switch to Python.
@EricChen Switch to Python - an interpreted and dynamically typed language from Java - 'compiled and statically typed language' because of coding syntax and number lines differ? Not a good idea.
11

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[]{});
answered Jul 20, 2010 at 20:21

5 Comments

ups, const is not Java! public static final Foo[] FOO = {}
why would it be public?
@Zoltán - why not? It's immutable, so doesn't present a safety issue. It's a little bit of clutter, but could be useful in other code, so is generally harmless. Maybe even create a central class with all of these constants, and then use import static to get at them.
@Jules the reference to the array is immutable, but the contents of it aren't. Anyone outside the class can replace the elements of the array freely. And on the other hand, as a rule of thumb, I believe all fields should be made private until they are needed outside the class.
Being zero length, there are no contents that can be changed
10

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.

answered Jul 26, 2018 at 18:33

Comments

6

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

Foo[] foos = Iterables.toArray(x, Foo.class);
answered May 28, 2019 at 18:57

Comments

3

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).

answered Jul 20, 2010 at 22:43

1 Comment

See my comment on doublep's answer about thread safety, which also applies to this solution. new Bar[0] avoids the issue.
2

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);
} 
answered Jul 20, 2010 at 20:34

Comments

1

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])
answered Sep 15, 2021 at 19:46

Comments

0

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

answered Mar 12, 2022 at 14:40

Comments

-1

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
Eric Aya
70.1k36 gold badges190 silver badges266 bronze badges
answered Jan 17, 2019 at 13:02

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.