我有一个实体员工
class Employee{
private String name;
private String addr;
private String sal;
}
现在我有这些员工的名单。我想过滤掉名称为null并设置addr ='A'的对象。我能够达到如下目标:
List<Employee> list2= list.stream()
.filter(l -> l.getName() != null)
.peek(l -> l.setAddr("A"))
.collect(Collectors.toList());
现在list2将拥有名称不为null的所有员工,然后将addr设置为这些员工的A. 我还想找到的是那些被过滤的员工(名称== null)并将其保存在DB中。我实现的方式如下:
List<Employee> list2= list.stream()
.filter(l -> filter(l))
.peek(l -> l.setAddr("A"))
.collect(Collectors.toList());
private static boolean filter(Employee l){
boolean j = l.getName() != null;
if(!j)
// save in db
return j;
}
1)这是正确的方法吗?
2)我们可以直接在lambda表达式中执行此操作而不是编写单独的方法吗?
答案 0 :(得分:4)
通常,您应该不在行为参数中使用副作用。请参阅“Stateless behaviors” and “Side-effects” of the package documentation部分。此外,建议不要将peek
用于非调试目的,请参阅“In Java streams is peek really only for debugging?”
尝试将所有这些不同的操作压缩到单个Stream管道中没有多大优势。考虑清洁的替代方案:
Map<Boolean,List<Employee>> m = list.stream()
.collect(Collectors.partitioningBy(l -> l.getName() != null));
m.get(false).forEach(l -> {
// save in db
});
List<Employee> list2 = m.get(true);
list2.forEach(l -> l.setAddr("A"));
关于你的第二个问题,一个lambda表达式允许几乎所有东西,一个方法。不同之处在于声明,即您不能声明其他类型参数也不能注释返回类型。但是,您应该避免在lambda表达式中编写太多代码,因为当然,您无法创建直接调用该代码的测试用例。但这是编程风格的问题,而不是技术限制。
答案 1 :(得分:0)
如果你可以使用peek来实现你的逻辑(虽然不建议除非学习),你可以做以下事情:
List<Employee> list2= list.stream()
.peek(l -> { // add this peek to do persistence
if(l.getName()==null){
persistInDB(l);
}
}).filter(l -> l.getName() != null)
.peek(l -> l.setAddr("A"))
.collect(Collectors.toList());
您也可以这样做:
List<Employee> list2 = list.stream()
.filter(l->{
boolean condition = l.getName()!=null;
if(condition){
l.setAddr("A");
} else {
persistInDB(l);
}
return condition;
})
.collect(Collectors.toList());
希望这有帮助!