I need to convert a list of ids to array of ids. I can do it in many ways but not sure which one should be used.
Say,
1. ids.stream().toArray(Id[]::new)
2. ids.toArray(new Id[ids.length])
Which one is more efficient and why?
I need to convert a list of ids to array of ids. I can do it in many ways but not sure which one should be used.
Say,
1. ids.stream().toArray(Id[]::new)
2. ids.toArray(new Id[ids.length])
Which one is more efficient and why?
java-11 introduced Collection::toArray
that has this implementation:
default <T> T[] toArray(IntFunction<T[]> generator) {
return toArray(generator.apply(0));
}
To make it simpler in your case, it is actually doing : ids.toArray(new Id[0])
; that is - it is not specifying the total expected size.
This is faster than specifying the size and it's non-intuitive; but has to do with the fact that if the JVM can prove that the array that you are allocating is going to be overridden by some copying that is immediately followed, it does not have to do the initial zeroing of the array and that proves to be faster then specifying the initial size (where the zeroing has to happen).
The stream approach will have (or try to guess an estimate) an initial size that the stream internals will compute, because:
ids.stream().toArray(Id[]::new)
is actually:
ids.stream().toArray(size -> Id[size]);
and that size
is either known or estimated, based on the internal characteristics that a Spliterator
has. If the stream reports SIZED
characteristic (like in your simple case), then it's easy, size
is always known. On the other hand if this SIZED
is not present, stream internals will only have an estimate of how many elements will be present and in such a case, an hidden new collection will be used to capture elements, called SpinedBuffer
.
You can read more here, but the approach ids.toArray(new Id[0])
will be the fastest.