图中　Head　用于表示第一个Stage,即调用调用诸如　Collection.stream()　方法产生的Stage,很显然这个Stage里不包含任何操作;　StatelessOp　和StatefulOp　分别表示无状态和有状态的Stage,对应于无状态和有状态的中间操作。　Stream流水线组织结构示意图如下:　图中通过　Collection.stream()　方法得到　Head　也就是stage0,紧接着调用一系列的中间操作,不断产生新的Stream。　这些Stream对象以双向链表的形式组织在一起,构成整个流水线,由于每个Stage都记录了前一个Stage和本次的操作以及回调函数,依靠这种结构就能建立起对数据源的所有操作　。这就是Stream记录操作的方式。　操作如何叠加?　以上只是解决了操作记录的问题,要想让流水线起到应有的作用我们需要一种将所有操作叠加到一起的方案。你可能会觉得这很简单,只需要从流水线的head开始依次执行每一步的操作(包括回调函数)就行了。这听起来似乎是可行的,但是你忽略了前面的Stage并不知道后面Stage到底执行了哪种操作,以及回调函数是哪种形式。换句话说,只有当前Stage本身才知道该如何执行自己包含的动作。这就需要有某种协议来协调相邻Stage之间的调用关系。　这种协议由　Sink　接口完成,　Sink　接口包含的方法如下表所示:　方法名　作用　void　begin(long　size)　开始遍历元素之前调用该方法,通知Sink做好准备。　void　end()　所有元素遍历完成之后调用,通知Sink没有更多的元素了。　boolean　cancellationRequested()　是否可以结束操作,可以让短路操作尽早结束。　void　accept(T　t)　遍历元素时调用,接受一个待处理元素,并对元素进行处理。Stage把自己包含的操作和回调方法封装到该方法里,前一个Stage只需要调用当前Stage.accept(T　t)方法就行了。　有了上面的协议,相邻Stage之间调用就很方便了,每个Stage都会将自己的操作封装到一个Sink里,前一个Stage只需调用后一个Stage的accept()　方法即可,并不需要知道其内部是如何处理的。当然对于有状态的操作,Sink的begin()　和end()　方法也是必须实现的。比如St