Java 8流中的forEach vs forEachOrdered

forEach vs forEachOrdered in Java 8 Stream

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

例子:

1
2
3
4
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));

输出:

1
2
3
4
5
6
7
8
forEach Demo
Output:AAA
Output:BBB
Output:CCC
forEachOrdered Demo
Output:AAA
Output:BBB
Output:CCC

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


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

第二行将始终输出

1
2
3
Output:AAA
Output:BBB
Output:CCC

而第一个是不保证的,因为订单没有保存。forEachOrdered将按流源指定的顺序处理流元素,而不管流是顺序的还是并行的。

引用forEachjavadoc:

The behavior of this operation is explicitly nondeterministic. For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism.

forEachOrderedjavadoc声明(强调mine)时:

Performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order.


虽然forEach较短,看起来更漂亮,但我建议在所有需要订单明确说明的地方使用forEachOrdered。对于顺序流,forEach似乎尊重顺序,甚至流API内部代码也使用forEach(对于已知为顺序流的流),在语义上需要使用forEachOrdered!然而,您可能稍后决定将流更改为并行,您的代码将被破坏。同样,当您使用forEachOrdered时,代码的阅读器会看到消息:"订单在这里很重要"。因此,它更好地记录了您的代码。

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

最后,两个forEachforEachOrdered都很少有用。在大多数情况下,您实际上需要产生一些结果,而不仅仅是副作用,因此像reducecollect这样的操作应该更合适。通过forEach表达自然还原操作通常被认为是一种不好的方式。


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

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

举个例子:

1
2
3
4
5
6
7
8
9
10
11
    String str ="sushil mittal";
    System.out.println("****forEach without using parallel****");
    str.chars().forEach(s -> System.out.print((char) s));
    System.out.println("
****forEach with using parallel****"
);

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

    str.chars().parallel().forEachOrdered(s -> System.out.print((char) s));

输出:

****不使用parallel的foreach***

苏希米塔尔

****使用parallel的foreach***

米胡尔伊斯斯塔特

****使用parallel进行foreachored***

苏希米塔尔