java 8 parallelStream() 与 sorted()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19529982/
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-12 18:03:37  来源:igfitidea点击:

java 8 parallelStream() with sorted()

javalambdaparallel-processingjava-8java-stream

提问by Eng.Fouad

JDK 8 EA is out now, and I am just trying to get used to the lambda and the new Stream API. I've tried to sort a list with parallel stream, but the result is always wrong:

JDK 8 EA 现已发布,我只是想习惯 lambda 和新的 Stream API。我试图用并行流对列表进行排序,但结果总是错误的:

import java.util.ArrayList;
import java.util.List;

public class Test
{
    public static void main(String[] args)
    {
        List<String> list = new ArrayList<>();
        list.add("C");
        list.add("H");
        list.add("A");
        list.add("A");
        list.add("B");
        list.add("F");
        list.add("");

        list.parallelStream() // in parallel, not just concurrently!
            .filter(s -> !s.isEmpty()) // remove empty strings
            .distinct() // remove duplicates
            .sorted() // sort them
            .forEach(s -> System.out.println(s)); // print each item
    }
}

OUTPUT:

输出:

C
F
B
H
A

Note that each time the output is different. My questions is, is it a bug? or is it not possible to sort a list in parallel? if so, then why the JavaDoc doesn't state that? Last question, is there another operation whose output would differ depending on the stream type?

请注意,每次输出都不同。我的问题是,这是一个错误吗?或者无法并行排序列表?如果是这样,那为什么 JavaDoc 没有说明呢?最后一个问题,是否还有其他操作的输出会因流类型而异?

采纳答案by Louis Wasserman

You need to use forEachOrdered, not forEach.

您需要使用forEachOrdered,而不是forEach

As per the forEachdoc:

根据forEach文档:

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. For any given element, the action may be performed at whatever time and in whatever thread the library chooses. If the action accesses shared state, it is responsible for providing the required synchronization.

对于并行流管道,此操作不保证遵守流的遇到顺序,因为这样做会牺牲并行性的好处。对于任何给定的元素,可以在库选择的任何时间和线程中执行该操作。如果动作访问共享状态,它负责提供所需的同步。

回答by cemal

In addition, you can read more about parallelism and forEachOrdered with a very nice example from here. In summary, using forEachOrdered in a parallel stream might result to lose the benefits of parallelism.

此外,你可以阅读更多关于并行性和forEachOrdered一个非常好的例子来自这里。总之,在并行流中使用 forEachOrdered 可能会导致失去并行性的好处。

Here the example from the same resource:

这是来自同一资源的示例:

Integer[] intArray = {1, 2, 3, 4, 5, 6, 7, 8 };
List<Integer> listOfIntegers =
    new ArrayList<>(Arrays.asList(intArray));

System.out.println("listOfIntegers:");
listOfIntegers
    .stream()
    .forEach(e -> System.out.print(e + " "));
System.out.println("");

System.out.println("listOfIntegers sorted in reverse order:");
Comparator<Integer> normal = Integer::compare;
Comparator<Integer> reversed = normal.reversed(); 
Collections.sort(listOfIntegers, reversed);  
listOfIntegers
    .stream()
    .forEach(e -> System.out.print(e + " "));
System.out.println("");

System.out.println("Parallel stream");
listOfIntegers
    .parallelStream()
    .forEach(e -> System.out.print(e + " "));
System.out.println("");

System.out.println("Another parallel stream:");
listOfIntegers
    .parallelStream()
    .forEach(e -> System.out.print(e + " "));
System.out.println("");

System.out.println("With forEachOrdered:");
listOfIntegers
    .parallelStream()
    .forEachOrdered(e -> System.out.print(e + " "));
System.out.println("");

And the output is

输出是

listOfIntegers:
1 2 3 4 5 6 7 8
listOfIntegers sorted in reverse order:
8 7 6 5 4 3 2 1
Parallel stream:
3 4 1 6 2 5 7 8
Another parallel stream:
6 3 1 5 7 8 4 2
With forEachOrdered:
8 7 6 5 4 3 2 1

The fifth pipeline uses the method forEachOrdered, which processes the elements of the stream in the order specified by its source, regardless of whether you executed the stream in serial or parallel. Note that you may lose the benefits of parallelism if you use operations like forEachOrdered with parallel streams

第五个管道使用 forEachOrdered 方法,该方法按其源指定的顺序处理流的元素,无论您是以串行还是并行方式执行流。请注意,如果将 forEachOrdered 之类的操作与并行流一起使用,则可能会失去并行性的好处

.

.