布尔值流,是真的吗?

时间:2014-10-10 17:25:16

标签: java lambda parallel-processing java-8 java-stream

我想使用并行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))

3 个答案:

答案 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));]

More inspiration here.