流——中间操作和终端操作之间特殊的操作顺序

mic*_*wth 0 java java-stream

import java.util.stream.*;

public class MyClass {
    public static void main(String args[]) {
      Stream.of(1, 2, 3).map(i -> {
          System.out.println(i+":inside map");
          return i+4;
       }).forEach(t->System.out.println(t + ":inside foreach"));
    }
}
Run Code Online (Sandbox Code Playgroud)

// 印刷:

1:inside map
5:inside foreach
2:inside map
6:inside foreach
3:inside map
7:inside foreach
Run Code Online (Sandbox Code Playgroud)

输出不应该是:

1:inside map
2:inside map
3:inside map
5:inside foreach
6:inside foreach
7:inside foreach
Run Code Online (Sandbox Code Playgroud)

我的印象是,每个中间操作结束后,它都会返回一个新的流。所以 foreach 应该得到 (5,6,7) 并因此打印

 5:inside foreach
 6:inside foreach
 7:inside foreach
Run Code Online (Sandbox Code Playgroud)

但案例表明,foreach 是对map 的每个条目一一执行的。这是为什么?

Pat*_*man 5

这是因为它map()确实是一个中间操作,但它也是一个无状态的操作。来自文档(https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps):

中间操作又分为无状态操作和有状态操作。无状态操作(例如过滤器和映射)在处理新元素时不保留先前看到的元素的状态 - 每个元素都可以独立于其他元素上的操作进行处理。有状态操作(例如不同和排序)可以在处理新元素时合并先前看到的元素的状态。

这意味着每当您的元素映射到新元素时,它都可以立即由管道的其余部分处理,而无需等待所有元素先被映射。这显然过于简单化了,但我只是想解释一下总体思路。