Java-11 представил Collection::toArray
, который имеет эту реализацию:
default <T> T[] toArray(IntFunction<T[]> generator) {
return toArray(generator.apply(0));
}
Чтобы сделать его проще в вашем случае, он на самом деле делает: ids.toArray(new Id[0])
; то есть - он не указывает общий ожидаемый размер.
Это быстрее, чем указание размера, и это не интуитивно понятно; но это связано с тем фактом, что если JVM может доказать, что выделенный вами массив будет переопределен с помощью некоторого копирования, которое следует сразу же, ему не нужно выполнять начальное обнуление массива, и это оказывается быстрее, чем указание начального размера (где должно происходить обнуление).
Потоковый подход будет иметь (или пытаться угадать оценку) начальный размер, который будет вычисляться внутренними компонентами потока, потому что:
ids.stream().toArray(Id[]::new)
на самом деле:
ids.stream().toArray(size -> Id[size]);
и что size
является либо известным, либо оценочным, исходя из внутренних характеристик, которыми обладает Spliterator
. Если поток сообщает характеристику SIZED
(как в вашем простом случае), то все просто, size
всегда известен. С другой стороны, если этого SIZED
нет, внутренние компоненты потока будут иметь только оценку того, сколько элементов будет присутствовать, и в таком случае для сбора элементов будет использоваться скрытая новая коллекция, называемая SpinedBuffer
.
Вы можете прочитать больше здесь , но подход ids.toArray(new Id[0])
будет самым быстрым.