Все, пожалуйста, на самом деле прочитайте этот вопрос, прежде чем вы увидите "поток" и "массив" и просто предположите , что вопрос является дубликатом. Я знаю как преобразовать поток в массив. Этот вопрос очень специфичен: как выполнить договор Collection.toArray(T[] array)
. Все эти люди говорят, что это дубликат: другие ответы повторно используют существующий массив, если он достаточно большой? Помечают ли они элемент null
, если существующий массив слишком большой? (Нет и нет.)
Я знаю, что интерфейс Java Stream<>
предоставляет несколько способов преобразования потока в массив. Но метод Collection.toArray(T[] array)
немного отличается. Он имеет несколько умных (на тот момент) требований, в том числе:
- Если массив, который вы передаете, достаточно большой, то массив, который вы передаете, должен использоваться; в противном случае должен быть создан новый.
- Если массив больше необходимого, после последнего элемента необходимо добавить
null
.
Так что, если моя Collection<T>
реализация извлекает свои значения из некоторого Stream<FooBar>
(со стратегией конвертации, которая преобразуется в T
, как я могу преобразовать мой поток в массив, требуемый для Collection.toArray(T[] array)
?
Без долгих раздумий, похоже, я должен сделать это:
@Override
public <T> T[] toArray(T[] array) {
try (final Stream<FooBar> stream = getStream()) {
T[] result = stream.map(converter::toT).toArray(length ->
(T[])Array.newInstance(array.getClass(), length));
if(result.length <= array.length) {
System.arraycopy(result, 0, array, 0, result.length);
if(result.length < array.length) {
array[result.length] = null;
}
result = array;
}
}
return result;
}
Но есть ли более краткий способ сделать это? Есть ли способ, которым я мог бы передать поток непосредственно в данный массив, если это возможно? И обеспечивает ли API Stream<>
что-то вроде этого: создание массива, как ожидает API Collection<>.toArray(T[] array)
?