基于条件集对象值并使用Java8流返回布尔值
我有嵌套列表,并且能够在条件为真时设置isMatched和department.setMatchedStatus(真)基于条件集对象值并使用Java8流返回布尔值,java,java-8,java-stream,Java,Java 8,Java Stream,我有嵌套列表,并且能够在条件为真时设置isMatched和department.setMatchedStatus(真) boolean isMatched = false; for (Employee employee: company.getEmployees()) { for (Department department: employee.getDepartments()) { if(departmentList.contains(department.getDep
boolean isMatched = false;
for (Employee employee: company.getEmployees()) {
for (Department department: employee.getDepartments()) {
if(departmentList.contains(department.getDepartmentName())){
isMatched = true;
department.setMatchedStatus(true);
}
}
}
return isMatched;
我想使用Java8流实现同样的功能,我尝试使用下面的代码,但无法返回布尔值
isMatched = company.getEmployees().stream()
.flatMap(employee-> employee.getDepartments().stream())
.filter((department) -> departmentList.contains(department.getDepartmentName()))
.forEach((department) -> department.setMatchedStatus(true));
有人能帮我吗?您可以在流上使用“peek()”方法,它允许您在不改变流内容的情况下使用流中的项目。更新每个对象后,只需知道是否有匹配的对象
return company.getEmployees().stream()
.flatMap(employee-> employee.getDepartments().stream())
.filter((department) -> departmentList.contains(department.getDepartmentName()))
.peek((department) -> department.setMatchedStatus(true))
.count() > 0;
这里的困难在于您需要执行两个副作用:设置
部门
对象上的匹配状态,以及设置本地标志值以确定是否存在任何匹配。在中使用peek
和count
的方法将起作用,因为在这种情况下,我们可以确保count
不会短路。但是,在维护过程中可能会导致问题。如果有人复制并重新排列这段代码,它可能会因为短路而无声地中断,这将是相当微妙的
也许更好的方法是将副作用打包到forEach
操作中。这使用AtomicBoolean
作为可变的“框”来解决无法改变捕获的局部变量的问题。它也比单元素阵列技巧更可取,因为原子在流并行运行的情况下是安全的
这还使用了lambda语句,我通常倾向于避免使用该语句。在这种情况下,情况并不太糟糕,而且它清楚地表明,多重副作用正在发生
AtomicBoolean isMatched = new AtomicBoolean(false);
company.getEmployees().stream()
.flatMap(employee -> employee.getDepartments().stream())
.filter(department -> departmentList.contains(department.getDepartmentName()))
.forEach(department -> {
department.setMatchedStatus(true);
isMatched.set(true);
});
return isMatched.get();
对我来说,最明确的解决办法是:
Set<Department> matchingDepartments =
company.getEmployees().stream()
.flatMap(employee -> employee.getDepartments().stream())
.filter(department -> departmentList.contains(department.getDepartmentName()))
.collect(Collectors.toSet());
matchingDepartments.forEach(department -> department.setMatchedStatus(true));
return !matchingDepartments.isEmpty();
设置匹配部门=
company.getEmployees().stream()
.flatMap(employee->employee.getDepartments().stream())
.filter(department->departmentList.contains(department.getDepartmentName()))
.collect(收集器.toSet());
matchingDepartments.forEach(department->department.setMatchedStatus(true));
回来!匹配部门。i空();
在生成中间
集时,它的效率稍低,但从代码可读性的角度来看,它比其他建议的变体要好。您的原始代码也不会返回bool。您只需设置属性,stream()代码也会这样做。很抱歉,实际上我错过了它,我将只进行编辑。编辑-count()
应该使用流。它可能会,但不能保证它会。我模模糊糊地记得关于基于数组的流优化等的讨论,我将试图找到一些相关信息。Javadoc说count()
相当于return-mapToLong(e->1L).sum()代码>和是一个减少操作。似乎它应该消耗整个流。@绿巨人,在这种特殊情况下它仍然有效,因为存在flatMap
和filter
流大小事先未知。但是,这种代码风格(即使用peek
进行非调试)肯定是不好的。流中任何对象的变化在某个时候都会有问题。流并不是真正为有状态对象的变化而设计或优化的。如果对象模型是不可变的,那么流的使用可能会更干净、更习惯。