Подтвердить что ты не робот

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?

4b9b3361

Ответ 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());