Java 8流短路

标签 java java-8 java-stream short-circuiting

阅读了一些关于 Java 8 的内容,我找到了 this博客文章解释了一些关于流和它们的减少,以及什么时候可以短路减少。底部写着:

Note in the case of findFirst or findAny we only need the first value which matches the predicate (although findAny is not guaranteed to return the first). However if the stream has no ordering then we’d expect findFirst to behave like findAny. The operations allMatch, noneMatch and anyMatch may not short-circuit the stream at all since it may take evaluating all the values to determine whether the operator is true or false. Thus an infinite stream using these may not terminate.

我知道 findFirstfindAny 可能会使归约短路,因为一旦找到元素,就不需要进一步处理。

但是为什么这对于 allMatchnoneMatchanyMatch 是不可能的?对于allMatch,如果发现一个不匹配谓词,就可以停止处理。没有人也一样。 anyMatch 对我来说尤其没有意义,因为它几乎等同于 findAny(返回的内容除外)?

对于findFirst/Any来说,也可以说这三个可能不会短路,因为它可能需要评估所有的值。

我是否遗漏了一些根本的区别?我真的不明白发生了什么吗?

最佳答案

有一个微妙的区别,因为 anyMatch 系列使用谓词,而 findAny 系列没有。从技术上讲,findAny() 看起来像 anyMatch(x -> true)anyMatch(pred) 看起来像 filter(pred).findAny ()。所以这里我们有另一个问题。考虑我们有一个简单的无限流:

Stream<Integer> s = Stream.generate(() -> 1);

因此,对此类流应用 findAny() 确实总是会短路并完成,而应用 anyMatch(pred) 取决于谓词。然而,让我们过滤我们的无限流:

Stream<Integer> s = Stream.generate(() -> 1).filter(x -> x < 0);

生成的流也是无限的吗?这是一个棘手的问题。它实际上不包含任何元素,但要确定这一点(例如,使用 .iterator().hasNext()),我们必须检查无限数量的底层流元素,因此此操作永远不会完成。我也将这种流称为无限流。然而,使用这样的流 anyMatchfindAny 将永远不会完成:

Stream.generate(() -> 1).filter(x -> x < 0).anyMatch(x -> true);
Stream.generate(() -> 1).filter(x -> x < 0).findAny();

所以 findAny() 也不能保证完成,它取决于之前的中间流操作。

总而言之,我认为该博文极具误导性。在我看来,无限流行为在官方 JavaDoc 中得到了更好的解释。 .

关于Java 8流短路,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32192846/

相关文章:

java - 使用 onCreateView 中的功能动态更改 View

java - 从列表中提取包含重复项的列表,并获取非重复列表java 8流

java - 使用流和收集器创建嵌套映射

java - 如何在流 API 中使用 system.out 重写计数循环

java - 如何从java中的线程更新MySql数据库

java - HQL 中的常量枚举值

java - 无法更改 Mac OS 外观中的 JProgressBar 颜色

java-8 - Akka actor 和 Java8 CompletableFuture 可以安全地结合在一起吗?

java - 函数式风格验证算法

java - Java 流中的中间操作