在这种情况下,中间流和终端流方法如何工作

Huy*_*ran 4 java java-stream

我在Java中有这个代码片段:

List<Integer> li= Arrays.asList(1, 2, 3, null, 4, 5, null, 6, 7, 8);
li.stream().filter(e-> e!=null)
           .map(e-> {System.out.print(" m "+ e); return e * 2;})
           .filter(e-> e % 3 == 0)
           .forEach(e-> {System.out.println(" fe " + e);});
Run Code Online (Sandbox Code Playgroud)

输出是

 m 1 m 2 m 3 fe 6
 m 4 m 5 m 6 fe 12
 m 7 m 8
Run Code Online (Sandbox Code Playgroud)

我知道filter,map是中间方法,这意味着它们只有在调用像forEach这样的终端方法时才会开始工作.但我不能只围绕它们被调用的确切顺序,并在这种情况下开始工作.有人可以向我解释这个输出是怎么来的吗?

And*_*kin 6

让代码本身讲述它的故事.

这是您的代码,附加打印输出:

import java.util.*;
import java.util.stream.*;

public class StreamEvaluationOrder {
    private static void p(String s) {
        System.out.println(s);
    }
    public static void main(String[] args) {
        List<Integer> li= Arrays.asList(1, 2, 3, null, 4, 5, null, 6, 7, 8);

        li.stream()
            .map(x -> { p("The element " + x + " is pulled from the list"); return x; })
            .filter(e-> { 
                boolean res = e != null; 
                if (res) p(e + " is not null");
                else p(e + " is null, therefore filtered out.\n"); 
                return res;
            })
            .map(e-> { 
                int res = e * 2; 
                p(e + " is mapped to " + res); 
                return res;
            })
            .filter(e-> {
                boolean res = e % 3 == 0;
                if (res) p(e + " is divisible by three");
                else p(e + " is not divisible by three, therefore filtered out. \n");
                return res;
            })
            .forEach(e-> {
                p(e + " reaches the forEach.\n");
            });
    }
}
Run Code Online (Sandbox Code Playgroud)

这是它告诉你的故事:

The element 1 is pulled from the list
1 is not null
1 is mapped to 2
2 is not divisible by three, therefore filtered out. 

The element 2 is pulled from the list
2 is not null
2 is mapped to 4
4 is not divisible by three, therefore filtered out. 

The element 3 is pulled from the list
3 is not null
3 is mapped to 6
6 is divisible by three
6 reaches the forEach.

The element null is pulled from the list
null is null, therefore filtered out.

The element 4 is pulled from the list
4 is not null
4 is mapped to 8
8 is not divisible by three, therefore filtered out. 

The element 5 is pulled from the list
5 is not null
5 is mapped to 10
10 is not divisible by three, therefore filtered out. 

The element null is pulled from the list
null is null, therefore filtered out.

The element 6 is pulled from the list
6 is not null
6 is mapped to 12
12 is divisible by three
12 reaches the forEach.

The element 7 is pulled from the list
7 is not null
7 is mapped to 14
14 is not divisible by three, therefore filtered out. 

The element 8 is pulled from the list
8 is not null
8 is mapped to 16
16 is not divisible by three, therefore filtered out. 
Run Code Online (Sandbox Code Playgroud)

原理是它逐个从源流中提取元素,将每个元素推送到整个管道,然后才开始处理下一个元素.现在更清楚了吗?