【问题标题】:Is Stream.count() guranteed to visit each element?Stream.count() 是否保证访问每个元素?
【发布时间】:2016-12-27 22:46:16
【问题描述】:

换句话说,以下行是否保证打印num行?

int num = list.stream().peek(System.out::println).count();

这个问题是由https://stackoverflow.com/a/41346586/2513200的cmet中的一个讨论引发的

我依稀记得一个讨论,避免迭代的优化可能是合法的,但在快速搜索过程中没有找到任何结论。

JavaDocs for Stream.count 包含以下声明:

这是归约的一种特殊情况,相当于:
return mapToLong(e -> 1L).sum();

但我不确定如果流能够以某种短路方式确定结果,这是否能提供任何保证。

【问题讨论】:

  • 将在 Java 9 中进行修改(参见 API 说明):download.java.net/java/jdk9/docs/api/java/util/stream/…
  • result 是等效的,不保证执行任何操作。
  • 在文档的那部分之后,您会发现:“如果实现可以直接从流源计算计数,则可以选择不执行流管道 [...]。在这种情况下,不会遍历任何源元素,也不会评估任何中间操作。"

标签: java java-8 java-stream


【解决方案1】:

不,不是。由于优化了 count() 实现,它不会在 Java 9 中执行此操作(如果预先知道流大小,它将跳过迭代)。

请参阅JDK-8067969 了解更多详情。 JDK-9 中的文档已相应更新:

如果实现可以直接从流源计算计数,则可以选择不执行流管道(顺序或并行)。在这种情况下,不会遍历源元素,也不会评估任何中间操作。有副作用的行为参数,除了调试等无害的情况外,强烈建议不要使用,可能会受到影响。

【讨论】:

  • 当后备拆分器为 SIZED 时,很可能会跳过迭代。
  • @Jean-FrançoisSavard,更准确地说,如果最后一个流具有 SIZED StreamOpFlag。 StreamOpFlags 类似于 spliterator 的特性,但有些不同。如果您有中间操作,则没有它们的拆分器,但您有 StreamOpFlags。使用中间 map()peek() 你很好,但中间 filter()distinct() 将清除 SIZED。
猜你喜欢
  • 1970-01-01
  • 2016-06-26
  • 1970-01-01
  • 2018-12-07
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
  • 2010-11-23
相关资源
最近更新 更多