[英]Java streams, filter based on condition in an object, set value to a string and a an array
[英]Based on condition set object value and return boolean using java 8 streams
如果条件为真,我有嵌套列表,并且能够设置isMatched和department.setMatchedStatus(true)。
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;
我想使用Java 8流实现相同的效果,我尝试使用下面的代码,但无法返回布尔值。
isMatched = company.getEmployees().stream()
.flatMap(employee-> employee.getDepartments().stream())
.filter((department) -> departmentList.contains(department.getDepartmentName()))
.forEach((department) -> department.setMatchedStatus(true));
有人可以帮我吗?
这里的困难是您要执行两个副作用:在Department
对象上设置匹配状态,并设置本地标志值以确定是否存在任何匹配。 在sisyphus答案中使用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();
您可以在Stream上使用'peek()'方法,该方法允许您在不更改流内容的情况下使用流中的项目。 更新每个对象后,您只需要知道是否有匹配项即可。
return company.getEmployees().stream()
.flatMap(employee-> employee.getDepartments().stream())
.filter((department) -> departmentList.contains(department.getDepartmentName()))
.peek((department) -> department.setMatchedStatus(true))
.count() > 0;
对我来说,最明确的解决方案是:
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();
由于生成中间Set
,它的效率有所降低,但从代码可读性的角度来看,它比其他建议的变体更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.