Java Stream API – 并行流和顺序流

huangapple go评论82阅读模式
英文:

Java Stream API - Parallel and Sequential Streams

问题

我对Stream API还不熟悉。我对Stream API有一个关于并行流和顺序流的问题。问题是:例如,我有一个类似这样的伪代码:

someStream
    .parallel()
    .filter(some_predicate)
    .sequential()
    .map(some_mapping_function)
    .terminal_operation();

Stream API会并行执行过滤操作,然后顺序执行映射操作吗?还是它仅仅改变流的“并行特性”,因此在这个示例中,流将变为顺序流?

英文:

I am new to the Stream API.I have a question about Stream API,specifically the parallel and sequential stream. The question is:if,for example,i have a pseudo-code like this:

someStream
    .parallel()
    .filter(some_predicate)
    .sequential()
    .map(some_mapping_function)
    .terminal_operation();

Is the Stream API going to execute filter in parallel and mapping sequentially,or does it merely change the "parallel-characteristic" of the stream,so,in this example,the stream is going to be sequential?

答案1

得分: 6

sequential()parallel() 的调用只是改变整个流的执行模式。无论在终端操作被调用时流处于哪种模式,都将使用该模式。在您的情况下,由于 sequential()parallel() 之后,您的流将会按顺序执行。

这在 Stream 接口中有记录:

>流管道可以顺序或并行执行。这种执行模式是流的属性 [强调添加]。流是使用初始的顺序或并行执行选择创建的。(例如,Collection.stream() 创建一个顺序流,Collection.parallelStream() 创建一个并行流。)可以通过 BaseStream.sequential()BaseStream.parallel() 方法修改这种执行模式的选择,并且可以使用 BaseStream.isParallel() 方法查询该模式。

还有 java.util.stream 包中的说明:

>流管道在顺序或并行模式下执行,具体取决于对终端操作调用时流的模式。可以使用 BaseStream.isParallel() 方法确定流的顺序或并行模式,可以使用 BaseStream.sequential()BaseStream.parallel() 操作修改流的模式。最近的顺序或并行模式设置适用于整个流管道的执行 [强调添加]

英文:

The calls to sequential() and parallel() simply change the mode of the entire stream. Whichever mode the stream is in when a terminal operation is invoked is the mode used. In your case, since sequential() is after parellel() your stream will be executed sequentially.

This is documented by the Stream interface:

>Stream pipelines may execute either sequentially or in parallel. This execution mode is a property of the stream [emphasis added]. Streams are created with an initial choice of sequential or parallel execution. (For example, Collection.stream() creates a sequential stream, and Collection.parallelStream() creates a parallel one.) This choice of execution mode may be modified by the BaseStream.sequential() or BaseStream.parallel() methods, and may be queried with the BaseStream.isParallel() method.

And the java.util.stream package:

>The stream pipeline is executed sequentially or in parallel depending on the mode of the stream on which the terminal operation is invoked. The sequential or parallel mode of a stream can be determined with the BaseStream.isParallel() method, and the stream's mode can be modified with the BaseStream.sequential() and BaseStream.parallel() operations. The most recent sequential or parallel mode setting applies to the execution of the entire stream pipeline [emphasis added].

答案2

得分: 2

创建一个非常简单的测试是获得这样的问题的答案的最快方法。我尝试了以下类似的方法:

public static void main(String args[]) {
    List<Integer> list = new ArrayList<>();
    for (int i=0; i<50; i++){
        list.add(i);
    }

    list.stream()
        .sequential()
        .map(a ->{
            System.out.println("sequential " + a); 
            return a;
        })
        .parallel()
        .forEach(a -> System.out.println("parallel " + a));
    
    System.out.println();
    System.out.println();
    
    list.stream()
        .parallel()
        .map(a ->{
            System.out.println("parallel " + a); 
            return a;
        })
        .sequential()
        .forEach(a -> System.out.println("sequential " + a));
}

当你运行代码并分析这两个流的输出时,你会发现第一个是并行的,第二个是顺序的。

基于此,我们可以推断只有最后一个 parallel/sequential 调用是重要的 - 它基本上覆盖了该标志。

英文:

The quickest way to get an answer to such question is to create a very simple test. I've tried something like so:

public static void main(String args[]) {
    List&lt;Integer&gt; list = new ArrayList&lt;&gt;();
    for (int i=0; i&lt;50;i++){
        list.add(i);
    }

    list.stream()
        .sequential()
        .map(a-&gt;{
            System.out.println(&quot;sequential &quot; + a); 
            return a;
        })
        .parallel()
        .forEach(a-&gt; System.out.println(&quot;parallel &quot; + a));
    
    System.out.println();
    System.out.println();
    
    list.stream()
        .parallel()
        .map(a-&gt;{
            System.out.println(&quot;parallel &quot; + a); 
            return a;
        })
        .sequential()
        .forEach(a-&gt; System.out.println(&quot;sequential &quot; + a));
}

When you run the code and analyse the output of both of those streams you can see that the first one was parallel and the second one was sequential.

Based on that we can deduce that only the last parallel/sequential call matters - it is basicly overwriting the flag.

huangapple
  • 本文由 发表于 2020年7月27日 17:48:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/63112716.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定