谈谈个人对于Java 8 Stream 流设计的理解

114 阅读2分钟

其实我认为,本质上就是两个东西,一个是流,一个是流操作(需要区分中间操作和终端操作)。

在jdk的体系,其实归根结底就是 PileLine + Sink + Terminal(TerminalSink)(这里单独把终端操作抽出来)

附上一张图

image.png 这张图里,我没有把各种细枝末节全摆上来,因为我认为,理解jdk 8,最核心的部分其实就是 pipeline、sink、terminalSink、terminalOp这几个概念,同时,我也没提到关于并发流的部分,那一部分过于复杂,对于理解流本身没有太多意义。

流运行的具体步骤:

编码阶段:

  1. 流的定义,如:stream().map().filter().collect();

代码执行阶段:

  1. 需要区分调用中间操作和终端操作

    a.中间操作,往往是记录操作,并且返回一个操作后得到的新流对象。

    b. 终端操作,则是触发数据流动以及处理的节点了(当然终端操作本身也是需要处理数据的)。

  2. 终端操作代码调用时需要做的事情

    a. 收集所有中间/终端操作,得到操作链,如何收集呢? 从终端操作对应的流开始,向source流收集,收集的效果: Sink0 -> Sink1 -> SinkEnd,得到了一个操作链。

    b. 通过某种方式,拿到source流对应的数据,将所有数据依次传入 操作链,至此,数据开始流动,并被操作链处理,并基于不同的终端操作,收集结果。

注:

终端操作的结果:其实就是保存在终端操作对应的Sink中,比如reduce,那么对应的sink会保存一个容器,比如match,则对应的sink会保存一个boolean的结果值。

终端操作类型:有结果的如match、reduce等,无结果的如foreach。

关于命名: pipeline就是管道,sink相当于连接管道的那个阀门,terminal相当于水龙头。

当你打开水龙头的时候,水从源pipeline流进来,经过sink的时候被处理(比如加糖?加颜料?),然后最终水龙头可能也加装一个净水器(terminalSink),最终得到结果。

上面这段话应该可以帮助理解流框架中的几个关键概念。