我想使用并行Stream并行化以下代码片段:
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))
答案 0 :(得分:95)
Streams API实际上对您的要求提供了一流的支持:
setOfE.parallelStream().anyMatch(e->eval(e));
与使用reduce
的方法相反,这可以保证进行短路评估并最佳地利用并行性。
答案 1 :(得分:18)
不,减少不支持短路评估。原因是reduce
只接受任意BinaryOperator
实现,并且不知道短路特定操作的可能性。
但是你可以更简单地执行整个操作:
setOfE.parallelStream().filter(e -> eval(e)).findAny().isPresent()
这只是搜索eval
返回true
的任意项,而findAny
允许在一个线程遇到匹配时立即结束操作。由于您对特定匹配Optional
不感兴趣,因此可以查询生成的Element
是否为空。
另外,您可以按照Marko Topolnik的评论建议使用
setOfE.parallelStream().anyMatch(e -> eval(e))
答案 2 :(得分:0)
我有一个案例,我不想想缩短我的操作。
我需要处理我所有的值,那么流的最终结果应该是一个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));]