Java 8 Stream中的forEach vs forEachOrdered

gst*_*low 71 java foreach java-8 java-stream

我知道这些方法的执行顺序不同,但在我的所有测试中,我都无法实现不同的顺序执行.

例:

System.out.println("forEach Demo");
Stream.of("AAA","BBB","CCC").forEach(s->System.out.println("Output:"+s));
System.out.println("forEachOrdered Demo");
Stream.of("AAA","BBB","CCC").forEachOrdered(s->System.out.println("Output:"+s));
Run Code Online (Sandbox Code Playgroud)

输出:

forEach Demo
Output:AAA
Output:BBB
Output:CCC
forEachOrdered Demo
Output:AAA
Output:BBB
Output:CCC
Run Code Online (Sandbox Code Playgroud)

请提供两种方法产生不同输出的示例.

Tun*_*aki 75

Stream.of("AAA","BBB","CCC").parallel().forEach(s->System.out.println("Output:"+s));
Stream.of("AAA","BBB","CCC").parallel().forEachOrdered(s->System.out.println("Output:"+s));
Run Code Online (Sandbox Code Playgroud)

第二行将始终输出

Output:AAA
Output:BBB
Output:CCC
Run Code Online (Sandbox Code Playgroud)

而第一个不保证,因为订单没有保留.forEachOrdered无论流是顺序流还是并行流,它都将按其源指定的顺序处理流的元素.

引自forEachJavadoc:

此操作的行为明确是不确定的.对于并行流管道,此操作不保证遵守流的遭遇顺序,因为这样做会牺牲并行性的好处.

forEachOrderedJavadoc陈述(强调我的):

如果流具有已定义的遭遇顺序,则按流的遭遇顺序对此流的每个元素执行操作.

  • 是的,你是对的.是否只能用于parallelStreams? (6认同)
  • 即使它现在只适用于并行流 - 我并不是说它确实如此 - 如果某些中间步骤得到优化以利用无序流,它仍然可能在未来中断,例如,排序可能会使用不稳定的算法,如果流是无序的. (6认同)
  • @BhushanPatil是的,这是对的./sf/ask/3313577781/ (3认同)

Tag*_*eev 27

虽然forEach更短,看起来更漂亮,但我建议forEachOrdered在订单重要的每个地方使用,以明确指定这一点.对于顺序流,forEach似乎遵守顺序甚至流API内部代码使用 forEach(对于已知为顺序的流),在语义上需要使用它forEachOrdered!不过,您可能稍后决定将您的流更改为并行,您的代码将被破坏.此外,当您使用forEachOrdered代码的阅读器时,会看到以下消息:"此处的顺序很重要".因此,它更好地记录您的代码.

还要注意,对于并行流,forEach不仅以非确定性顺序执行,而且还可以在不同的线程中同时执行它以用于不同的元素(这是不可能的forEachOrdered).

最后两个forEach/ forEachOrdered很少有用.在大多数情况下,您实际上需要产生一些结果,而不仅仅是副作用,因此操作喜欢reducecollect应该更合适.表达逐渐减少操作forEach通常被认为是一种不好的风格.

  • "最后,forEach/forEachOrdered都很少有用".我十分同意.看来这些方法被过度使用了. (7认同)
  • @RealSkeptic,你是真正的怀疑论者!`Stream.of("a","b","c").flatMap(s - > Stream.of("1","2","3").map(s :: concat)).spliterator ().hasCharacteristics(Spliterator.ORDERED)`返回true,因此必须确定结果流的顺序.如果您认为JDK文档应该明确说明这一点,请随时提交错误. (2认同)

小智 10

forEach()方法对此流的每个元素执行一个操作。对于并行流,此操作不能保证维持流的顺序。

forEachOrdered()方法对此流的每个元素执行一个操作,以确保对具有定义的遇到顺序的流按遇到顺序处理每个元素。

请看下面的例子:

    String str = "sushil mittal";
    System.out.println("****forEach without using parallel****");
    str.chars().forEach(s -> System.out.print((char) s));
    System.out.println("\n****forEach with using parallel****");

    str.chars().parallel().forEach(s -> System.out.print((char) s));
    System.out.println("\n****forEachOrdered with using parallel****");

    str.chars().parallel().forEachOrdered(s -> System.out.print((char) s));
Run Code Online (Sandbox Code Playgroud)

输出:

**** for每个不使用并行****

苏菲尔·米塔尔

**** for每个使用并行****

米苏尔·伊斯特拉特

**** forEachOrdered使用并行****

苏菲尔·米塔尔