我仍然在学习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));
似乎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表达式?
答案 0 :(得分:47)
忘记与第一个代码段相关联。我根本不会使用forEach
。由于您要将Stream
的元素收集到List
中,因此使用Stream
结束collect
处理会更有意义。然后,您需要peek
才能设置ID。
List<Entry> updatedEntries =
entryList.stream()
.peek(e -> e.setTempId(tempId))
.collect (Collectors.toList());
对于第二个片段,forEach
可以执行多个表达式,就像任何lambda表达式一样:
entryList.forEach(entry -> {
if(entry.getA() == null){
printA();
}
if(entry.getB() == null){
printB();
}
if(entry.getC() == null){
printC();
}
});
但是(查看您的评论尝试),您无法在此方案中使用过滤器,因为您只会处理某些条目(例如,entry.getA() == null
的条目)。 / p>
答案 1 :(得分:8)
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());
}
});
答案 2 :(得分:6)
在第一种情况下,替换为多行forEach
,您可以使用peek
流操作:
entryList.stream()
.peek(entry -> entry.setTempId(tempId))
.forEach(updatedEntries.add(entityManager.update(entry, entry.getId())));
在第二种情况下,我建议将循环体提取到单独的方法,并使用方法引用通过forEach
调用它。即使没有lambdas,它也会使你的代码更加清晰,因为循环体是独立的算法,它处理单个条目,所以它在其他地方也很有用,可以单独测试。
编辑问题后更新。如果您检查了异常,那么您有两个选择:将它们更改为未选中的或者根本不在这段代码中使用lambdas / streams。
答案 3 :(得分:3)
您不必将多个操作塞入一个流/ lambda。考虑将它们分成2个语句(使用静态导入toList()
):
entryList.forEach(e->e.setTempId(tempId));
List<Entry> updatedEntries = entryList.stream()
.map(e->entityManager.update(entry, entry.getId()))
.collect(toList());
答案 4 :(得分:0)
我的首选方法是将 java.util.function.Consumer<?>
与 andThen(...)
连接起来。
应用于你的例子,可以写成:
entryList.stream()
.forEach(
((Consumer<Entry>) entry -> entry.setTempId(tempId))
.andThen(entry -> updatedEntries.add(entityManager.update(entry, entry.getId())))
);
这样看,读起来不太好……但是您可以将 2 个使用者移动到本地函数变量中,它会变得像:
Consumer<Entry> c1 = entry -> entry.setTempId(tempId);
Consumer<Entry> c2 = entry -> updatedEntries.add(entityManager.update(entry, entry.getId()));
entryList.stream().forEach(c1.andThen(c2));
你可以像这样编写你的消费者组合:
public static <T> Consumer<T> combine(Consumer<? super T>... consumers){
return (T t) -> Arrays.stream(consumers).forEach(c -> c.accept(t));
}
它允许重写上面的例子:
entryList.stream()
.forEach(combine(
entry -> entry.setTempId(tempId),
entry -> updatedEntries.add(entityManager.update(entry, entry.getId()))));
希望Consumer
类有一个方法可以组合多个相同类型的消费者,也许这个combine
已经存在于某处而我不知道,所以我邀请您搜索?< /p>