RFR(s): 8060192: Add default method Collection.toArray(generator)

Stuart Marks stuart.marks at oracle.com
Tue Jun 19 00:08:09 UTC 2018



Tagir Valeev wrote:

>> If you are going to create long-living array which is likely to be empty,
>> it's good to deduplicate them to spare the heap space. This can be easily
>> done via existing toArray method like
>> collection.toArray(MyClass.EMPTY_ARRAY) assuming we have an empty array
>> constant. We use this pattern very often in IntelliJ IDEA source code (e.
>> g. think of method which returns an array of Java member annotations; often
>> there are none). New generator methods is much less convenient for this:
>> toArray(s -> s == 0?MyClass.EMPTY_ARRAY:new MyClass[s]). I'm actually
>> missing a method accepting an empty array instead of generator in the
>> Stream API. And I don't think that new collection method is useful. The
>> existing one is perfect.

Rémi Forax wrote:

> we can expect the VM to not allocate the array if once inlined the code is
>    new MyClass[0].getClass()
> 
> if it's not the case, i think it's a better idea to tweak the VM rather than try to change an API based on a pattern that should not be necessary.

I think the two of you are talking about different things. Tagir is concerned 
about *long-lived* zero-length arrays, whereas Rémi is talking about the 
possibility of short-circuiting the allocation of a zero-length array if it's 
replaced by a nonzero-length array and thus has an extremely short life.

Tagir, if your use case is that you know you are creating lots of long-lived 
zero-length arrays, and you want to deduplicate them, then sure, using 
toArray(MyClass.EMPTY_ARRAY) is a fine thing to do. There are a bunch of 
assumptions here about the longevity and frequency of creation of such arrays. 
Having a shared empty array might indeed be the right thing for the IntelliJ 
IDEA code base, but that doesn't mean it's true in general. The 
toArray(generator) might be perfectly fine for many code bases even if it isn't 
suitable for the one you have in mind.

You also mention the lack of a <T> T[] Stream.toArray(T[]) method. This would 
seem to help the case of sharing a zero-length array, but 
Collection.toArray(T[]) also has odd semantics that we didn't want to replicate 
in streams. The point of that method is to *reuse* the argument array. The odd 
semantics are that, when the argument array is longer than necessary, null is 
added after the last written element. Instead of replicating the semantics of 
Collection.toArray(T[]) on Stream, we ended up with Stream.toArray(generator) 
instead.

Now maybe the Stream.toArray() overloads aren't sufficient for what you want to 
do, in which case you might want to propose something. But that sounds like a 
different discussion.

s'marks


More information about the core-libs-dev mailing list