图文分解Java8Stream源码的奥秘
小伙伴们好呀,我是 4ye,今天来分享下 Java8 Stream 的源码
核心回顾stream 是一次性的,不是数据结构,不存储数据,不改变源数据.。
API 分为终端和中间操作,中间操作是惰性的,碰到终端才去执行。
中间操作有无状态和有状态之分,有状态需要更改上一步操作获得的所有元素,才可以进行下一步操作,比如 排序 sorted,去重 distinct,跳过 skip,限制 limit 这四个,需要多迭代一次。
终端操作有短路与否之分,短路操作有 anyMatch, allMatch, noneMatch, findFirst, findAny 整体概览
这里列出一些重要的类,是看源码过程中必须了解的。
源码中涉及到 N 多的内部类,这个是删减后的版本
比如 : Sink 接口是数据实际操作的地方,核心方法: begin,accept,end AbstractPipeline 抽象类是核心的数据结构,双链表 demo代码
这里沿用上文的例子 Student aStud = new Student(1, "a"); Student bStud = new Student(2, "b"); Student cStud = new Student(3, null); // 集合的创建 一 List collect1 = Stream.of(aStud, bStud, cStud).collect(Collectors.toList()); collect1.forEach(System.out::println); List studNameList = studentList.stream() .map(Student::getName) .filter(Objects::nonNull) .map(String::toUpperCase) .sorted() .map(e -> e + "c") .collect(Collectors.toList()); 步骤解析
都在这里了
这里步骤太多了,就不一一放出来了 ,列下核心 wrapSink, 创建 Sink 链 ,将管道的 Sink 操作连接在一起 copyInto , 处理数据 wrapSink()
开始套娃,从 ReducingSink 往前套
opWarpSink 方法调用的是每一步 中间操作 中的方法
通过 单链表 的形式将他们联系在一起
Sink 链创建结果
copyInto()
这里判断是不是 短路操作 ,然后就去执行 Sink 的 begin,accept,end 方法。
通过 forEachRemaining 进行内部迭代,这个是 Spliterator 的方法。
map 链节点,直接调用传进来的方法,
filter 链节点,多一步判断
sorted 节点,添加到 list 中。 注意,此时没有继续调用 downstream.accept 方法!
意味着,我们代码中的 5 个中间步骤只执行了前 3 个。
不过别担心, sorted 链节点中它重写了这个 end,并开启对新数据的 新一轮遍历 !
这就是我们提到的, 有状态中间操作多一次迭代的原因
最后呢,是来到终止操作 TerminalOp 中的 accept,这里执行的是 list 的 add 方法(我们调用 Collectors.toList() 中构建的),至此,数据添加到 state 中
获取数据,ReducingSink 继承了 Box 这个抽象类,最后 get 方法得到结果。
总结
代码对应的 执行流程 先创建流,出现了 Head 节点 创建中间管道 Pipeline 调用终端操作后有三步 (一)将中间管道的 Sink 操作连接在一起 ( wrapSink ) (二)处理数据 (copyInto ),主要调用 Sink 中的 begin,accept (核心),end 操作 (三)返回结果,ReducingSink 中的 get 方法
主要记住这个 wrapSink 方法 和 copyInto 方法。
一个套娃,一个调用 begin,accept,end 等方法。
那么,这个 stream 的 原理机制 就出来了:
利用 wrapSink 方法将各个中间操作中的 Sink 嵌套 在一起,然后来到 copyInto 方法,调用 begin 通知各个 Sink 做好准备,接着进行 内部迭代 调用 accept 方法,再调用 end 方法完成数据的操作,最后通过 get 方法,获取新容器中的数据,便是结果了。
此外,源码的 链式调用API 写法 ,设计模式 的使用以及 泛型 ,四大函数式接口 组合构建的高度抽象,封装写法,对我们的编码能力,源码阅读能力也有很大的帮助!
比如 这个 Consumer+Function 接口的组合,配合泛型上下限的使用
源码中 访问者模式 ,工厂模式 等设计模式的影子 访问者模式: 将数据结构与数据操作分离 。
对应源码:数据结构是 Pipeline ,操作是 Sink
工厂模式
对 stream 的特点更加熟悉
比如: stream 是一次性的,不是数据结构,不存储数据,不改变源数据.。 中间操作是惰性的,遇到 终端操作才真正执行 有状态的中间操作的特殊之处在于多迭代一次 内部迭代 终端操作主要做了两件事,串连中间操作,调用 accept 方法处理数据 最后
有所收获的话,别忘了 三连(点赞,在看,转发) 鼓励下 4ye 呀,谢谢&下期见!
晴天里的眼泪一个女人在哭泣。不管她哭得多么伤心,人们只是看到一种景象,那个女孩子在哭。看得再仔细,带着再好奇的心,然而,那只是一幕。没有谁能懂得女人的内心痛苦。哪怕是她再亲密的对象,再亲密的人
橘子不要直接吃了,加入1勺面粉,出锅好看又好吃,实在太解馋了橘子不要直接吃了,加入1勺面粉,出锅好看又好吃,实在太解馋了。说到橘子,相信大家都很熟悉,也经常吃,橘子是我们最常见的水果之一,口味酸甜,非常地开胃,当季的橘子价格便宜,所以深得人
这个颜色的裙子太好看了!MSMK2023流行色穿搭!Heygirls我是代班编辑dada。每年12月,权威色彩机构Pantone都会公布下一年的年度流行色,2023年的流行色也已经于去年12月公布啦!是活
23年过去,美国髦精夫妇的街拍又火了?!网友感叹时尚是个轮回最近,一组20多年前的街拍火了。主角是小肯尼迪夫妇约翰肯尼迪(小肯尼迪)和卡罗琳贝赛特。棕发英挺的小肯尼迪,金发飒爽的卡罗琳。照片里,他们的穿搭20多年过去也丝毫不过时。身着剪裁讲
158女生适合长裙还是短裙?答案不能一概而论,关键还得看这三点不同身材的女性在穿搭方面的选择不同,比如小个子和高个子适合的搭配方式,适合的单品都是不同的,158女生适合长裙还是短裙这个问题就曾经让很多女孩子纠结,但其中的答案其实并不能一概而论
昔日老厂房变身时尚新地标,太好逛了新春逛杨浦昔日老厂房今日时尚聚集地不出上海就能体验好吃的好玩的还能感受杨浦滨江的美景新年第一站上海国际时尚中心藏不住了,推荐给您!上海国际时尚中心在杨浦百年工业博览带南段尾端,有一座占地约1
紫外线消毒灯或损害室内空气质量使用紫外线杀菌辐射(UVGI)方式对室内空间进行消毒,是一种明显有效的灭活新冠病毒等各种病原体的方法。然而,据芬兰赫尔辛基大学团队发表在环境科学与技术快报杂志上的新研究显示,该方法
分享6种鸡蛋的花样做法,天天不重样!营养又美味说到鸡蛋,大家肯定都不陌生,鸡蛋蛋白质含量高,适当地食用可以帮助我们补充身体所需的营养。因此,它成为了大部分人早餐中不可或缺的一部分,尤其是在长身体的孩子每天也需要食用一个鸡蛋来补
鸡胸肉和这几个菜一起炒,营养丰富,味道鲜美,大人小孩都爱吃大家好!我是大叔爱生活美食,每天为大家分享几道好吃的家常菜美食,希望大家喜欢,鸡胸肉和什么配菜炒着好吃呢,今天就给你分享一道好吃的杂菜炒鸡胸肉,家里有什么就随便配菜炒了,今天我就用
数读降价效果不明显?小鹏汽车1月交付5218辆文懂车帝原创邢秋鸿懂车帝原创行业2月1日,小鹏汽车公布1月交付成绩。由于春节期间部分交付推迟,2023年1月小鹏汽车共交付5218辆,同比去年下跌近6成,环比下降超过50,其中G9
古人会如何形容香港十大美女岁月从不败美人,我们记忆中最无法忘怀的,大抵就是这一批港风美人了吧。她们的美各有各的风情,各有各的特点,也就只有充满意象的古诗词才能描绘出她们的韵味了。邱淑贞经珠不动凝两眉,铅华消