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