I have nested list and am able to set isMatched and department.setMatchedStatus(true) when if condition is 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;
Would like to achieve the same using java 8 streams, which i tried using below code, but couldn't return boolean.
isMatched = company.getEmployees().stream()
.flatMap(employee-> employee.getDepartments().stream())
.filter((department) -> departmentList.contains(department.getDepartmentName()))
.forEach((department) -> department.setMatchedStatus(true));
Could anyone help me on this please ?
解决方案
The difficulty here is that you have two side effects you want performed: setting the matched state on the Department object, and setting a local flag value to determine if there were any matches. The approach of using peek and count in sisyphus' answer will work, since in this case we can be assured that count won't short-circuit. However, it may cause problems under maintenance. If somebody were to copy and rearrange this code, it might silently break because of short-circuiting, and this would be quite subtle.
Perhaps a better approach is to pack the side effects into the forEach operation. This uses AtomicBoolean as a mutable "box" to work around the inability to mutate captured local variables. It's also preferable to the single-element array trick, as the atomics are safe in case the stream is run in parallel.
This also uses a statement lambda, which I generally prefer to avoid. In this case it's not too bad, and it makes clear that multiple side effects are occurring.
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();