【问题标题】:Stream of boolean values, is any true?布尔值流,是真的吗?
【发布时间】:2014-12-05 22:39:44
【问题描述】:
我想并行化使用 parallelStream 截断的以下代码:
boolean anyTrue() {
for (Element e : setOfE) {
if (eval(e)) {
return true;
}
}
return false;
}
以下是否适用于并行流并使用常规短路评估?
setOfE.parallelStream().map(e -> eval(e)).reduce(false, (a,b) -> a || b))
【问题讨论】:
标签:
java
lambda
parallel-processing
java-8
java-stream
【解决方案1】:
Streams API 实际上为您的要求提供一流的支持:
setOfE.parallelStream().anyMatch(e->eval(e));
与您使用 reduce 的方法相反,这可以保证进行短路评估并以最佳方式利用并行性。
【解决方案2】:
不,归约不支持短路评估。原因是reduce 只是接收一个任意的BinaryOperator 实现并且不知道短路特定操作的可能性。
但是您可以更简单地执行整个操作:
setOfE.parallelStream().filter(e -> eval(e)).findAny().isPresent()
这只是搜索eval 返回true 的任意项目,findAny 允许在一个线程遇到匹配项时立即结束操作。可以查询生成的 Optional 是否为空,因为您对特定匹配的 Element 不感兴趣。
您也可以按照 Marko Topolnik 的建议使用:
setOfE.parallelStream().anyMatch(e -> eval(e))
【解决方案3】:
我有一个案例,我不想想缩短我的操作。
我需要处理我所有的值,那么流的最终结果应该是anyMatch,基本上。但我实际上不能使用anyMatch,因为一旦找到true 值就会短路。
// WRONG for my case - need to process ALL field IDs
return fieldIs.stream()
.map(UUID::toString)
.anyMatch(fieldId -> processProjectForField(portfolioId, fieldId, projectId, fieldValueDataMap));
// RIGHT for my case - goes through all field IDs, and returns TRUE
// if there is at least one 'true' return from the processProjectForField method.
return fieldIs.stream()
.map(UUID::toString)
.map(fieldId -> processProjectForField(portfolioId, fieldId, projectId, fieldValueDataMap))
.reduce(Boolean.FALSE, Boolean::logicalOr);
// What you wrote is also acceptable
[...]
.reduce(false, (a,b) -> a || b));
// Another way of doing it
[...]
.collect(Collectors.reducing(Boolean.FALSE, Boolean::logicalOr));]
More inspiration here.