代码之家  ›  专栏  ›  技术社区  ›  Joseph Sible-Reinstate Monica

流。排序()。forEach()是否按预期工作?[副本]

  •  4
  • Joseph Sible-Reinstate Monica  · 技术社区  · 7 年前

    在从事Java项目时,我遇到了如下代码:

    someMap.keySet().stream().sorted().forEach(/* ... */);
    

    很明显,这里的意图是根据键的自然顺序为地图中的每个键做一些事情,这似乎是实际发生的事情。然而,我不确定这种行为是否有保证。 The Javadoc for Stream#forEach 说:

    此操作的行为明显不确定。对于并行流管道,此操作不能保证尊重流的相遇顺序,因为这样做会牺牲并行性的好处。对于任何给定的元素,可以在库选择的任何时间和线程中执行该操作。

    我知道如果代码使用 .parallelStream() 而不是 .stream() 虽然不能保证它能正常工作,但由于它使用的是顺序流(Javadoc没有提到),我不确定。这是保证始终工作,还是代码需要使用 .forEachOrdered() 而不是 .forEach() 就为了它?

    编辑:我相信这个问题不是重复的 forEach vs forEachOrdered in Java 8 Stream ,因为这个问题是在问“forEach和forEachOrdered的区别在一般情况下是什么”,而公认的答案基本上是“平行流”。这个问题是关于顺序流的。

    3 回复  |  直到 7 年前
        1
  •  10
  •   Ousmane D.    7 年前

    不能保证 forEach 终端操作将按遭遇顺序处理元素,因此 “显式不确定性” . 虽然在当前的实现中,它应该按照流的遭遇顺序处理序列流的元素。

    forEachOrdered 主要用于使用并行流的情况,如果流具有定义的遭遇顺序,则需要遵守流的遭遇顺序。

    使用 forEach公司 forEachOrdered公司 在连续的流上也会有相同的效果,所以这是一个偏好问题。

    如上所述,在当前的实施下,我们知道 forEach公司 终端操作应该按照流的遭遇顺序处理序列流的元素,但由于java文档中没有说明,因此最好保持中立,使用 forEachOrdered公司 如果您真的关心迭代顺序。

        2
  •  4
  •   Eugene    7 年前

    在当前实施下 是的,但文档中很清楚没有规定这一点。这显然可以改变,但目前情况并非如此,即使在进行以下操作时:

    Stream.of(5, 4, 3, 1)
          .unordered()
          .forEach(System.out::println);
    

    即使您故意打破顺序,对于顺序流,数据也不会被洗牌 故意地 内部-至少目前没有。

    不过,你必须小心,不要依赖它,因为不同版本之间可能会发生变化, here is one example

        3
  •  0
  •   Stephen C    7 年前

    这是保证始终工作,还是代码需要使用。forEachOrdered()而不是。forEach()是否为?

    不。它不能保证总是有效。正如javadoc所说 forEach() 方法可能不是确定性的。这意味着实施者有权更改以下情况 目前 表现不同的决定论。

    如果您想要保证确定性,请使用javadoc显式保证确定性的方法。在 .forEachOrdered() 在未来的版本中会被故意破坏。


    所以我会向该应用程序的维护人员指出这个错误。我们无法预测 将来会有突破,但肯定会。潜在的bug就是bug。