ArrayFactory SAM type / toArray

Joshua Bloch josh at
Wed Sep 19 14:48:10 PDT 2012


I don't find these arguments convincing.  There's no race (any more than
there is for any bulk operation) as the allocation is done by the object
itself.  The allocation stuff is pretty much a red herring: most users
don't preallocate the array. So it seems to me that using factories here
might amount to needless complexity and inconsistency.


On Wed, Sep 19, 2012 at 2:15 PM, Brian Goetz <brian.goetz at> wrote:

> Why passing a lambda that will be called in the body of the toArray ?
>> It's simpler to directly pass the array.
> No, that's what the existing unfortunate toArray(T[]) does.  Things that
> are wrong with it:
>  - If you get the size wrong, it has to reallocate.
>  - If it reallocates, it has to do it reflectively.
>  - It is inherently racy.
> To see the racy part, consider an implementation like SynchronizedList.
>  If the user does:
>  Foo[] array = c.toArray(new Foo[c.size()]);
> where c is a synchronized list, we acquire the lock, compute the size,
> release the lock, and pass the array into toArray, which will have to
> allocate again (reflectively) if the size has changed.  Whereas an
> implementation of toArray(ArrayFactory) can create the array once at the
> proper size while ensuring no concurrent modifications.
> So, comparing the status quo toArray(T[]) with the proposed (low quality)
> default version:
>  - Worst case is identical
>  - Best case is better in that allocation is not done reflectively
> And a non-crappy overriden implementation can be better still (eliminate
> races.)
> Arguably the proposed approach also provides a better separation of
> concerns; having the client allocate the array for the library seems
> questionable.  (Arguably it is even better from an API design perspective
> to pass a class literal rather than a lambda, but that gets us back into
> reflection.)
> Josh writes:
>  What problem are you trying solve?
> I think the above should explain, but in a nutshell the problem is: the
> two existing precedents for toArray as done in Collection are both
> unfortunate, and I'd rather not propagate them blindly into Streams.
> They're probably the best we could have done without lambdas in the
> language, but with lambdas, a better alternative arises -- let the library
> create the array with a factory provided by the caller.  I would like to
> offer a better version of toArray for Streams, and possibly consider
> retrofitting onto Collection.

More information about the lambda-libs-spec-observers mailing list