[英]Stream of boolean values, is any true?
I want to parallelize the following code snipped using a parallelStream:我想并行化使用parallelStream截取的以下代码:
boolean anyTrue() {
for (Element e : setOfE) {
if (eval(e)) {
return true;
}
}
return false;
}
Will the following work on parallel streams and use regular short-circuit evaluation?以下是否适用于并行流并使用常规短路评估?
setOfE.parallelStream().map(e -> eval(e)).reduce(false, (a,b) -> a || b))
Streams API actually has first-class support for your requirement: Streams API 实际上为您的需求提供一流的支持:
setOfE.parallelStream().anyMatch(e->eval(e));
As opposed to your approach with reduce
, this is guaranteed to have short-circuit evaluation and optimally leverage parallelism.与您使用
reduce
的方法相反,这可以保证进行短路评估并最佳地利用并行性。
No, reduction does not support short-circuit evaluation.不,减少不支持短路评估。 The reason is that
reduce
just receives an arbitrary BinaryOperator
implementation and has no idea about the possibilities of short-circuiting the particular operation.原因是
reduce
只接收任意的BinaryOperator
实现,并且不知道短路特定操作的可能性。
But you can perform the entire operation much simpler:但是您可以更简单地执行整个操作:
setOfE.parallelStream().filter(e -> eval(e)).findAny().isPresent()
This simply searches for an arbitrary item for which eval
returns true
and findAny
allows to end the operation as soon as one thread has encountered a match.这只是搜索
eval
返回true
的任意项目,并且findAny
允许在一个线程遇到匹配时立即结束操作。 The resulting Optional
can be queried for being empty as you are not interested in the particular matching Element
.由于您对特定匹配的
Element
不感兴趣,因此可以查询结果Optional
是否为空。
Alternatively you can use as suggested by Marko Topolnik's comment:或者,您可以按照 Marko Topolnik 评论的建议使用:
setOfE.parallelStream().anyMatch(e -> eval(e))
I have a case where I DON'T want to short-circuit my operations.我在那里,我不想短路我操作的情况。
I need to process all my values, then the final result of the stream should be an anyMatch
, basically.我需要处理我所有的值,那么流的最终结果应该是一个
anyMatch
,基本上。 But I can't actually use anyMatch
, because that will short-circuit as soon as it finds a true
value.但我实际上不能使用
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));]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.