Java 8 Stream 中的 forEach 与 forEachOrdered

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32797579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 13:07:12  来源:igfitidea点击:

forEach vs forEachOrdered in Java 8 Stream

javaforeachjava-8java-stream

提问by gstackoverflow

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.

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

采纳答案by Tunaki

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. forEachOrderedwill 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 forEachJavadoc:

引用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.

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

When the forEachOrderedJavadoc states (emphasis mine):

forEachOrderedJavadoc 声明(强调我的)时:

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

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

回答by Tagir Valeev

Although forEachshorter and looks prettier, I'd suggest to use forEachOrderedin every place where order matters to explicitly specify this. For sequential streams the forEachseems to respect the order and even stream API internal code usesforEach(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 forEachOrderedthe reader of your code sees the message: "the order matters here". Thus it documents your code better.

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

Note also that for parallel streams the forEachnot 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不仅以非确定性顺序执行,而且您还可以让它在不同线程中针对不同元素同时执行(这在 中是不可能的forEachOrdered)。

Finally both forEach/forEachOrderedare rarely useful. In most of the cases you actually need to produce some result, not just side-effect, thus operations like reduceor collectshould be more suitable. Expressing reducing-by-nature operation via forEachis usually considered as a bad style.

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

回答by Sushil Mittal

forEach()method performs an action for each element of this stream. For parallel stream, this operation does not guarantee to maintain order of the stream.

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

forEachOrdered()method performs an action for each element of this stream, guaranteeing that each element is processed in encounter order for streams that have a defined encounter order.

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

take below example:

以下面的例子为例:

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

Output:

输出:

****forEach without using parallel****

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

sushil mittal

苏尔米塔尔

****forEach with using parallel****

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

mihul issltat

米胡尔伊斯斯塔特

****forEachOrdered with using parallel****

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

sushil mittal

苏尔米塔尔