具有多个语句的Java 8 Lambda Stream forEach

Red*_*ddy 40 java lambda java-8

我还在学习Lambda,请原谅我如果我做错了什么

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));
Run Code Online (Sandbox Code Playgroud)

似乎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?
Run Code Online (Sandbox Code Playgroud)

如何将其转换为Lambda表达式?

Era*_*ran 53

忘了与第一个代码片段相关联.我根本不会用forEach.既然你是收集的元素Stream进入List,它会更有意义,以结束Stream与处理collect.然后,您需要peek设置ID.

List<Entry> updatedEntries = 
    entryList.stream()
             .peek(e -> e.setTempId(tempId))
             .collect (Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

对于第二个片段,forEach可以执行多个表达式,就像任何lambda表达式一样:

entryList.forEach(entry -> {
  if(entry.getA() == null){
    printA();
  }
  if(entry.getB() == null){
    printB();
  }
  if(entry.getC() == null){
    printC();
  }
});
Run Code Online (Sandbox Code Playgroud)

但是(查看您的注释尝试),您无法在此方案中使用过滤器,因为您只会处理某些条目(例如,其中的条目entry.getA() == null).

  • 不是建议 peek() 仅用于调试吗?我认为应该尝试一下map() (3认同)
  • 不幸的是我们不应该使用 peek...请参阅 https://rules.sonarsource.com/java/RSPEC-3864 (2认同)

小智 10

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());
  }
});
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是无效的语法。后面不是多了一个`}`吗? (3认同)

Tag*_*eev 6

在第一种情况下,除了多行之外,forEach您还可以使用peek流操作:

entryList.stream()
         .peek(entry -> entry.setTempId(tempId))
         .forEach(updatedEntries.add(entityManager.update(entry, entry.getId())));
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,我建议将循环体提取到单独的方法,并使用方法引用来调用它forEach.即使没有lambdas,它也会使你的代码更加清晰,因为循环体是处理单个条目的独立算法,因此它在其他地方也可能有用,并且可以单独测试.

问题编辑后更新.如果你检查了异常,那么你有两个选择:要么将它们更改为未经检查的,要么根本不在这段代码中使用lambdas/streams.

  • @Reddy在这种情况下,我看不出真正的优势,因为你可以在`peek`或`forEach`中执行`setTempId`调用,行为将类似.但是,如果您根本不使用`forEach`,而是使用collect,为了生成输出List(请参阅我的更新答案),您需要`peek`才能调用`setTempId`. (2认同)
  • 请记住`peek` [主要应该用于调试目的](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#peek-java.util .function.Consumer-).将副作用应用于流数据时使用`forEach`. (2认同)

Mis*_*sha 6

您不必将多个操作塞进一个流/lambda 中。考虑将它们分成 2 个语句(使用 的静态导入toList()):

entryList.forEach(e->e.setTempId(tempId));

List<Entry> updatedEntries = entryList.stream()
  .map(e->entityManager.update(entry, entry.getId()))
  .collect(toList());
Run Code Online (Sandbox Code Playgroud)