Java 8 Lambda Stream для каждого с несколькими операторами
Я все еще в процессе обучения Лямбде, пожалуйста, извините меня, если я что-то неправильно делал
final Long tempId = 12345L;
List<Entry> updatedEntries = new LinkedList<>();
for (Entry entry : entryList) {
entry.setTempId(tempId);
updatedEntries.add(entityManager.update(entry, entry.getId()));
}
//entryList.stream().forEach(entry -> entry.setTempId(tempId));
Кажется, что forEach
может выполняться только для одного утверждения. Он не возвращает обновленный поток или функцию для дальнейшей обработки. Возможно, я выбрал неправильный вариант.
Может ли кто-нибудь помочь мне, как это сделать эффективно?
Еще один вопрос,
public void doSomething() throws Exception {
for(Entry entry: entryList){
if(entry.getA() == null){
printA() throws Exception;
}
if(entry.getB() == null){
printB() throws Exception;
}
if(entry.getC() == null){
printC() throws Exception;
}
}
}
//entryList.stream().filter(entry -> entry.getA() == null).forEach(entry -> printA()); something like this?
Как преобразовать это в выражение Lambda?
Ответы
Ответ 1
Забыл относиться к первому фрагменту кода. Я бы вообще не использовал forEach
. Поскольку вы собираете элементы Stream
в List
, было бы более целесообразно завершить обработку Stream
с помощью collect
. Тогда вам понадобится peek
, чтобы установить идентификатор.
List<Entry> updatedEntries =
entryList.stream()
.peek(e -> e.setTempId(tempId))
.collect (Collectors.toList());
Для второго фрагмента forEach
может выполнять несколько выражений, как и любое лямбда-выражение:
entryList.forEach(entry -> {
if(entry.getA() == null){
printA();
}
if(entry.getB() == null){
printB();
}
if(entry.getC() == null){
printC();
}
});
Однако (глядя на вашу прокомментированную попытку) вы не можете использовать фильтр в этом сценарии, так как вы будете обрабатывать только некоторые записи (например, записи, для которых entry.getA() == null
), если вы это сделаете.
Ответ 2
В первом случае альтернативно многострочному forEach
вы можете использовать операцию потока peek
:
entryList.stream()
.peek(entry -> entry.setTempId(tempId))
.forEach(updatedEntries.add(entityManager.update(entry, entry.getId())));
Во втором случае я предлагаю извлечь тело цикла в отдельный метод и использовать ссылку на метод, чтобы вызвать его через forEach
. Даже без lambdas это сделает ваш код более понятным, поскольку тело цикла является независимым алгоритмом, который обрабатывает одну запись, поэтому может быть полезен и в других местах и может быть протестирован отдельно.
Обновление после редактирования вопроса. если вы проверили исключения, у вас есть два варианта: либо изменить их на непроверенные, либо вообще не использовать lambdas/streams в этом фрагменте кода.
Ответ 3
List<String> items = new ArrayList<>();
items.add("A");
items.add("B");
items.add("C");
items.add("D");
items.add("E");
//lambda
//Output : A,B,C,D,E
items.forEach(item->System.out.println(item));
//Output : C
items.forEach(item->{
System.out.println(item);
System.out.println(item.toLowerCase());
}
});
Ответ 4
Вам не нужно записывать несколько операций в один поток/лямбда. Рассмотрите разделение их на 2 оператора (используя статический импорт toList()
):
entryList.forEach(e->e.setTempId(tempId));
List<Entry> updatedEntries = entryList.stream()
.map(e->entityManager.update(entry, entry.getId()))
.collect(toList());