<< That English, No, Aussie, Accent | Home | CrossOver Mac: Coming August 2006 >>

How Do You Use Collection.toArray(Object[] a)?

There are two ways to do it. And it took me five minutes to figure out one isn't acctually used.

I'm working on some Java code, using J2SDK 1.4. And I needed to turn a java.util.ArrayList of Foo objects into an array of Foo objects. So naturally I thought about java.util.Collection's

public Object[] toArray(Object[] a)

method. It's been a while since I last used this method. So I surfed over to the Javadoc at Sun's Java website. The first thing that jumped into my eyes is this code sample:

String[] x = (String[]) v.toArray(new String[0]);

That's exactly what I needed (and eventually what I did.) However something else caught my eyes too:

If the collection fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this collection.

What that means is that if my List contains exactly three Foos, then I can either do:

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

or

Foo[] foos = new Foo[3];
list.toArray(foos);

to achieve the same result. The first alternative also works when we don't know the size of the List. The second alternative works only if I already know the size of the List. And the second way offers any advantage over the first only if the foos array can be reused in multiple toArray() calls. But if I know the size of the collection, I can probably avoid the use of List altogether.

How do you use Collection.toArray(Object[] a)? (I would really like to be educated about real world code where the second alternative wins over the first.)

Tags :


Re: How Do You Use Collection.toArray(Object[] a)?

The standard way to convert to a typed array is this: (String[])list.toArray(new String[list.size()]);

Re: How Do You Use Collection.toArray(Object[] a)?

That seems to be the optimal usage. Thanks.

Re: How Do You Use Collection.toArray(Object[] a)?

That breaks on multi-threaded environments unless you synchronize around both the size() and the toArray() call. Peace.

Re: How Do You Use Collection.toArray(Object[] a)?

Ah, multi-threading. It ruins everything now, doesn't it? :)

Strictly speaking, the code is not broken. The worse that can happen is if the size of the list grows larger after the list.size() call, in which case a new array will be allocated inside toArray(). We do waste an array allocation of a non-trivial size.

Do we go back to "(Foo[]) list.toArray(new Foo[0])"?

Re: How Do You Use Collection.toArray(Object[] a)?

It's not "broken" if the collection grows, but it is DEFINITELY broken if the array shrinks, because you don't known when "null" in the array is a "null" in the collection vs. when the collection has shrunk. Peace.

Re: How Do You Use Collection.toArray(Object[] a)?

For ArrayList and LinkedList passing an empty Array is just as broken in a multithreaded environment, if you do not make sure that no other thread modifies the array. The size of the list could change between the allocation of a new array and the copying of its elements.

Re: How Do You Use Collection.toArray(Object[] a)?

There are no multithreading issues, because List is not synchronized, anyway. If multiple threads can access a collection, you must synchronize it yourself. Creating and throwing away a new Foo[0] is cheap, as it will never leave the young GC pool, but doing (Foo[])list.toArray(new Foo[list.size()]) is still more efficient.

Re: How Do You Use Collection.toArray(Object[] a)?

The only advantage of the second method is that you save the time of creation of the useless new Foo[0] array. So it's rather a speed issue.

Re: How Do You Use Collection.toArray(Object[] a)?

The thrown away "new Foo[0]" bothered me a bit too. The suggestion in the first comment of passing in a "new Foo[list.size()]" is better approach. I wish the Javadoc mentioned this as an idiom.

Re: How Do You Use Collection.toArray(Object[] a)?

It's not a throw-away. You can do a static final of size 0 because it is truly a constant (i.e. immutable).

Re: How Do You Use Collection.toArray(Object[] a)?

OK, it really sounds like I ought to do this:

  class Foo {
    public static final Foo[] EMPTY_ARRAY = new Foo[0];
    ...
  }
  ...
  Foo[] foos = (Foo[]) list.toArray(Foo.EMPTY_ARRAY);

Thanks!


Add a comment Send a TrackBack