学习笔记——JavaStream源码学习-创新互联

思路

先上一段代码

目前创新互联建站已为超过千家的企业提供了网站建设、域名、雅安服务器托管、网站改版维护、企业网站设计、郫都网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
ListuserList = new ArrayList<>();

        for (int i = 0; i< 10; i++) {userList.add(new User(i, "wtq", "1234"));
        }
        userList.stream()
                .filter(user ->user.getUserId() >3)
                .filter(user ->user.getUserId() >4)
                .forEach(System.out::println);

Java的stream流, 平时很常用的功能, 让代码变的更简洁, 可读性也更好, 但是完全没有了解过它内部的逻辑. 今天有时间自己尝试梳理了一下源码, 这也算是我第一次独立分析源码, 写的不好还请见谅.

整体逻辑

先在前面总结一下整套流程的大体逻辑.
在学习stream的使用方法时, 就了解到一些流操作分为中间操作终止操作.中间操作并不会触发逻辑执行, 真正触发操作执行是终止操作.
一段流操作中的中间操作在内部使用AbstractPipeline被连接成双向链表的结构, 并使用Sink保存具体的操作方式(如上面的过滤逻辑).
直到有一个中间操作对象调用了终止操作.终止操作需要实现TerminalOpSink. 由终止操作构造Sink调用单向链表. 最终将Sink执行链委托给Spliterator调用.
重要的类
AbstractPipeline : 双向链表元素类
Sink : 操作链, 串联整个流操作中的具体逻辑的类
Spliterator : 真正遍历调用操作链的类
在这里插入图片描述
在这里插入图片描述
这里暂时听不明白没关系, 下面正式进入代码

读代码 stream()

从第一个方法开始分析.
在这里插入图片描述
这个方法构造了最初的Stream对象, 第一个参数是通过调用内部方法获取的.先不管这个参数.
在这里插入图片描述
点进StreamSupport提供的方法, 可以发现这里的Stream对象的实际类型是ReferencePipeline的内部类Head构造了双向链表的头.

filter() 中间操作

注意, 这里filter()其实是由Head对象调用的, 注意搞清楚this的值.
这里创建了一个StatelessOp.
在这里插入图片描述
继续追溯构造方法, 实际是调用了AbstractPipeline的构造方法, 此时构造对象的previousStage就是Head. 同时为previousStagenextStage赋值. 这时候, 双向链表已经有了两个元素.
这里想象一下第二个filter运行时, 会将上一个filter的StatelessOp对象作为previousStage, 执行相同的操作. 做完这些操作, 双向链表里加入了第三个元素.
在这里插入图片描述

foreach() 终止操作

此时终止操作是由最后一个中间操作调用
这里将终止操作的逻辑保存在ForEachOps对象中
在这里插入图片描述
在这里插入图片描述
终止操作调用最终评估方法, 将全部中间操作构成的链表传入方法
在这里插入图片描述
继续传递
在这里插入图片描述
在这里插入图片描述构造Sink单向链表
在这里插入图片描述
Sink链表传递给Spliterator
在这里插入图片描述
为每个元素调用Sink操作链
在这里插入图片描述

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


新闻名称:学习笔记——JavaStream源码学习-创新互联
文章出自:http://myzitong.com/article/dddcge.html