• 学习笔记——Java Stream 源码学习


    思路

    先上一段代码

            List<User> userList = 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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    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操作链
    在这里插入图片描述

  • 相关阅读:
    Vue+elementUI 导出word打印
    HLA-Face: Joint High-Low Adaptation for Low Light Face Detection 论文阅读笔记
    美食杰项目 -- 首页(一)
    Redis足足十二题,应该没有人能全对
    游戏引擎中为什么要用四元数表示旋转而不用欧拉角旋转?
    全量知识系统问题及SmartChat给出的答复 之13 解析器+DDD+文法型
    k8s集群开启临时容器配置
    Jenkins服务
    数据库的基本操作(6)
    【Transformers】第 7 章:文本表示
  • 原文地址:https://blog.csdn.net/qq_43585377/article/details/128016523