基于条件设置对象值并使用java 8流返回布尔值

时间:2016-12-27 13:48:56

标签: java java-8 java-stream

我有嵌套列表,如果条件为真,我可以设置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));

有人可以帮我吗?

3 个答案:

答案 0 :(得分:3)

这里的困难在于你有两个你想要执行的副作用:在Department对象上设置匹配状态,并设置一个本地标志值以确定是否有任何匹配。在sisyphus' answer中使用peekcount的方法是有效的,因为在这种情况下我们可以确保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();

答案 1 :(得分:2)

您可以在Stream上使用'peek()'方法,它允许您使用流中的项而不更改流的内容。在更新每个对象后,您只需要知道是否有匹配。

return company.getEmployees().stream()
               .flatMap(employee-> employee.getDepartments().stream())
               .filter((department) -> departmentList.contains(department.getDepartmentName()))
               .peek((department) -> department.setMatchedStatus(true))
               .count() > 0;

答案 2 :(得分: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的效率稍差,但从代码可读性的角度来看,它看起来比其他提议的变体更好。