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

时间:2018-01-22 17:48:41

标签: 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);});

输出

 m 1 m 2 m 3 fe 6
 m 4 m 5 m 6 fe 12
 m 7 m 8

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

3 个答案:

答案 0 :(得分:6)

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

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

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. 

以下是它告诉你的故事:

sp.edit().remove(ids).apply();

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

答案 1 :(得分:1)

  • m 11通过第一个过滤器,然后在打印后转换为2,然后不通过第二个过滤器。
  • m 2:都一样。
  • m3 fe 63传递第一个过滤器,然后转换为6,然后传递第二个过滤器。
  • m 4m 5:与1相同。
  • m 6 fe 12:与3相同。
  • m 7m 8:与1相同。

问题在于流中的每个元素都经过整个流水线(或者至少在它不被过滤之前),并且只有在那之后才会拾取下一个元素。

答案 2 :(得分:1)

将流视为管道。

一旦拨打forEach,号码就会开始通过管道。首先是1,然后在经过管道后,2来了,依此类推。

1遇到第一个filter。它不是空的吗?它是!继续!现在1到达map,它会被打印并加倍并变为2!继续!现在2(原1)到达第二个filter!不幸的是它不能被3整除,所以它的旅程就在那里停止了!

管道中的第二个数字2现已出现。大致相同的事情发生了。它会转换为43不能被3整除。旅程结束。

第三个数字filter通过,传递第一个6,打印,然后转换为filter,其中 可被3整除!所以它通过第二个forEach并打印在fe 6!乌拉!

这就是打印{ id int64 autoincremented email string UNIQUE username string UNIQUE hashedPassword string token string . . } 的原因。