views:

173

answers:

4

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

+18  A: 

Where x is the collection:

x.toArray (new Foo[x.size ()])
doublep
+1: Can't get any simpler than that. Although it does make me wonder why Roman didn't notice `toArray` in the `Collection` interface's documentation...
R. Bemrose
**simpler** (easier) but not best(memory): `x.toArray(new Foo[0])` --- **documentation**: no time to read...
Carlos Heuberger
Simplicity is key... think a few people will be kicking themselves hehe
David
@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
@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.
Andreas_D
@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 `:` ).
Carlos Heuberger
+3  A: 

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[]{});
Andreas_D
ups, `const` is not Java! `public static final Foo[] FOO = {}`
Carlos Heuberger
@Carlos - thanks!
Andreas_D
+1  A: 

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);
}    
OscarRyz
A: 

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

Roman