Java 8 Stream中的forEach vs forEachOrdered

时间:2015-09-26 13:12:04

标签: 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));

输出:

forEach Demo
Output:AAA
Output:BBB
Output:CCC
forEachOrdered Demo
Output:AAA
Output:BBB
Output:CCC

如果两种方法产生不同的输出,请提供示例。

4 个答案:

答案 0 :(得分:66)

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));

第二行将始终输出

Output:AAA
Output:BBB
Output:CCC
由于没有保留订单,因此第一个不能保证。 forEachOrdered将按照源指定的顺序处理流的元素,无论流是顺序流还是并行流。

引自forEach Javadoc:

  

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

forEachOrdered Javadoc陈述(强调我的)时:

  

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

答案 1 :(得分:25)

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

另请注意,对于并行流,forEachOrdered不仅以非威慑顺序执行,而且还可以在不同的线程中同时为不同的元素执行(forEach无法实现)

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

答案 2 :(得分:7)

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));

输出:

**** forEach不使用并行****

苏希尔·米塔尔

**** for每次使用并行****

mihul issltat

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

苏希尔·米塔尔

答案 3 :(得分:0)

如果我们将 forEachOrdered() 与并行流一起使用,我们可能会失去并行性的好处。

众所周知,如果我们使用 forEach() 方法,并行编程元素将并行打印。所以订单不会固定。但是在并行Streams中使用forEachOrdered()固定顺序。

Stream.of("AAA","BBB","CCC").forEachOrdered(s->System.out.println("输出:"+s)); 输出:AAA 输出:BBB 输出:CCC