#java #stream
#java #поток
Вопрос:
У меня есть список объектов, и я хочу сначала обработать каждый объект, а затем сопоставить их с другим объектом, а затем собрать их в список. Вот так:
list.stream().forEach(doSomething).map(mapFunction).collect()
Но Java Stream не поддерживает это, и я думаю, есть ли какой-нибудь элегантный способ добиться того же результата.
Комментарии:
1. Можете ли вы переместить
doSomething
операцию внутрьmapFunction
?2. Почему бы не заменить
forEach
наmap
!
Ответ №1:
list.stream().peek(doSomething).map(mapFunction).collect()
Комментарии:
1. Это решение кажется довольно хорошим, но я не понимаю, почему оно называется peek (). Предназначен ли он для решения этой ситуации?
2. Да, вы можете прочитать javadoc для этого метода. Он предназначен для создания таких цепочек: Stream.of(«один», «два», «три», «четыре») .filter(e -> e.length()> 3) .peek(e -> System.out.println(«Отфильтрованное значение: » e)) .map(Строка:: верхний регистр) .peek(e -> System.out.println(«Сопоставленное значение: » e)) .собирать(Коллекторы. ToList());
Ответ №2:
forEach
это операция терминала, поэтому вы не можете продолжать работать с потоком
Терминальные операции, такие как Stream.forEach или IntStream.sum, могут пересекать поток для получения результата или побочного эффекта. После выполнения операции терминала конвейер потока считается использованным и больше не может использоваться;
Вы можете перемещаться doSomething
внутри map
метода, чтобы он выполнялся во время сопоставления
В общем случае вместо этого используйте операцию сокращения
forEach() можно просто заменить операцией сокращения, которая более безопасна, эффективна и более поддается распараллеливанию
Ответ №3:
Вы не можете использовать map
after forEach
, поскольку forEach
не возвращает a Stream
.
Вы можете просто использовать свою forEach
логику внутри a map
, поскольку она в любом случае повторит всю вашу коллекцию:
list.stream().map(o -> {
// Foreach logic
System.out.println(o);
// Map
return o.toString();
});