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