简体   繁体   English

布尔值流,是真的吗?

[英]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));]

More inspiration here. 更多灵感在这里。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM