Ответ 1
Вы можете использовать Stream#generate
с limit
:
Stream.generate(MyClass::new).limit(10);
Скажем, я хочу создать n элементов. Pre Java 8, я бы написал:
List<MyClass> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
list.add(new MyClass());
}
Есть ли элегантный способ использования потока для создания n элементов?
Я подумал об этом:
List<MyClass> list = Stream.iterate(0, i -> i).limit(10)
.map(o -> new MyClass()).collect(Collectors.toList());
Есть ли стандартный/лучший способ кодирования этого?
Обратите внимание, что фактическое использование немного сложнее, и использование потока будет более гибким, потому что я могу сразу перекачать элементы через другие функции в одной строке, даже не создавая ссылку на список, например, группируя их:
Stream.iterate(0, i -> i).limit(10).map(o -> new MyClass())
.collect(Collectors.groupingBy(...));
Вы можете использовать Stream#generate
с limit
:
Stream.generate(MyClass::new).limit(10);
Если вы знаете n заранее, я думаю, что более идиоматично использовать один из источников потока, который создает поток, который, как известно, имеет ровно n элементов. Несмотря на появление, использование limit(10)
не обязательно приводит к потоку SIZED
с ровно 10 элементами - его может быть меньше. Наличие потока SIZED
улучшает расщепление в случае параллельного выполнения.
Как отметил в комментарии Sotirios Delimanolis, вы можете сделать что-то вроде этого:
List<MyClass> list = IntStream.range(0, n)
.mapToObj(i -> new MyClass())
.collect(toList());
Альтернативой является это, хотя мне это не ясно, лучше:
List<MyClass> list2 = Collections.nCopies(10, null).stream()
.map(o -> new MyClass())
.collect(toList());
Вы также можете сделать это:
List<MyClass> list = Arrays.asList(new MyClass[10]);
list.replaceAll(o -> new MyClass());
Но это приводит к списку фиксированного размера, но изменяемому.