在Java 8流中forEach和forEachOrdered。

时间:2021-08-20 19:10:08

I understand that these methods differ the order of execution but in all my test I cannot achieve different order execution.

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

Example:

例子:

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

Output:

输出:

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

Please provide examples when 2 methods will produce different outputs.

请举例说明两种方法将产生不同的输出。

2 个解决方案

#1


46  

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

The second line will always output

第二行总是输出。

Output:AAA
Output:BBB
Output:CCC

whereas the first one is not guaranted since the order is not kept. forEachOrdered will processes the elements of the stream in the order specified by its source, regardless of whether the stream is sequential or parallel.

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

Quoting from forEach Javadoc:

forEach Javadoc的引用:

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.

这个操作的行为是显式不确定性的。对于并行流管道,此操作不保证尊重流的遇到顺序,因为这样做会牺牲并行性的好处。

When the forEachOrdered Javadoc states (emphasis mine):

当forEachOrdered的Javadoc状态(强调我的):

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

对该流中的每个元素执行一个操作,如果流有一个已定义的冲突顺序,则在流的遇到顺序中执行。

#2


21  

Although forEach shorter and looks prettier, I'd suggest to use forEachOrdered in every place where order matters to explicitly specify this. For sequential streams the forEach seems to respect the order and even stream API internal code uses forEach (for stream which is known to be sequential) where it's semantically necessary to use forEachOrdered! Nevertheless you may later decide to change your stream to parallel and your code will be broken. Also when you use forEachOrdered the reader of your code sees the message: "the order matters here". Thus it documents your code better.

虽然forEach更短,看起来更漂亮,但我建议在每个订单事项明确指定的地方使用forEachOrdered。对于顺序流,forEach似乎尊重顺序,甚至是流API内部代码(对于已知的顺序流)使用forEachOrdered,这在语义上是必要的!尽管如此,您以后可能会决定将您的流更改为parallel,并且您的代码将被破坏。当您使用forEachOrdered时,您的代码的读者会看到这样的信息:“这里的顺序很重要”。这样可以更好地记录代码。

Note also that for parallel streams the forEach not only executed in non-determenistic order, but you can also have it executed simultaneously in different threads for different elements (which is not possible with forEachOrdered).

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

Finally both forEach/forEachOrdered are rarely useful. In most of the cases you actually need to produce some result, not just side-effect, thus operations like reduce or collect should be more suitable. Expressing reducing-by-nature operation via forEach is usually considered as a bad style.

最后,forEach/forEachOrdered很少有用。在大多数情况下,您实际上需要产生一些结果,而不仅仅是副作用,因此像reduce或collect这样的操作应该更合适。通过forEach来表达减少自然的操作通常被认为是一种糟糕的方式。

#1


46  

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

The second line will always output

第二行总是输出。

Output:AAA
Output:BBB
Output:CCC

whereas the first one is not guaranted since the order is not kept. forEachOrdered will processes the elements of the stream in the order specified by its source, regardless of whether the stream is sequential or parallel.

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

Quoting from forEach Javadoc:

forEach Javadoc的引用:

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.

这个操作的行为是显式不确定性的。对于并行流管道,此操作不保证尊重流的遇到顺序,因为这样做会牺牲并行性的好处。

When the forEachOrdered Javadoc states (emphasis mine):

当forEachOrdered的Javadoc状态(强调我的):

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

对该流中的每个元素执行一个操作,如果流有一个已定义的冲突顺序,则在流的遇到顺序中执行。

#2


21  

Although forEach shorter and looks prettier, I'd suggest to use forEachOrdered in every place where order matters to explicitly specify this. For sequential streams the forEach seems to respect the order and even stream API internal code uses forEach (for stream which is known to be sequential) where it's semantically necessary to use forEachOrdered! Nevertheless you may later decide to change your stream to parallel and your code will be broken. Also when you use forEachOrdered the reader of your code sees the message: "the order matters here". Thus it documents your code better.

虽然forEach更短,看起来更漂亮,但我建议在每个订单事项明确指定的地方使用forEachOrdered。对于顺序流,forEach似乎尊重顺序,甚至是流API内部代码(对于已知的顺序流)使用forEachOrdered,这在语义上是必要的!尽管如此,您以后可能会决定将您的流更改为parallel,并且您的代码将被破坏。当您使用forEachOrdered时,您的代码的读者会看到这样的信息:“这里的顺序很重要”。这样可以更好地记录代码。

Note also that for parallel streams the forEach not only executed in non-determenistic order, but you can also have it executed simultaneously in different threads for different elements (which is not possible with forEachOrdered).

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

Finally both forEach/forEachOrdered are rarely useful. In most of the cases you actually need to produce some result, not just side-effect, thus operations like reduce or collect should be more suitable. Expressing reducing-by-nature operation via forEach is usually considered as a bad style.

最后,forEach/forEachOrdered很少有用。在大多数情况下,您实际上需要产生一些结果,而不仅仅是副作用,因此像reduce或collect这样的操作应该更合适。通过forEach来表达减少自然的操作通常被认为是一种糟糕的方式。