Stream源码追踪

99 阅读2分钟
  • 持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情

前言

在jdk1.8加入了stream流后我们在处理列表数据的时候减少了很多重复繁杂的逻辑处理,但是列表是怎么做到使用steam流来处理数据的就需要来看一下它的实现原理了。

List

这里使用List举例来看一下,先创建List并使用stream方法

public static void main(String[] args) {
    List<User> list = new ArrayList();
    list.stream();
}

进入到stream到方法

image.png

可以看到是Collection接口定义的默认方法,如果子类不重写会走上图的执行逻辑,这样只要是Collection接口的子类都无需实现此方法,在List跟AraayList的源码里并没有发现设计Stream的方法

ArrayList的类图

image.png

Stream的流程

1. Stream对象

image.png

在源码中Stream的对象是直接通过StreamSupport.stream这个方法获取的,方法入参是一个方法跟false,接下里看StreamSupport.stream

1.1 StreamSupport.stream

image.png

在这个方法内先判断spliterator是否为空,为空直接抛异常,后续的流程就在ReferencePipeline的静态内部类Head中

1.2 ReferencePipeline.Head

image.png

Head是ReferencePipeline的静态内部类并且是它的子类,在这里看到后续逻辑指向了它的父类ReferencePipeline

image.png

跟到父类发现还是指向的父类,看一下类图

image.png

在类图中ReferencePipeline这个类继承类AbstractPipeline这个类,并且继承了Stream,这就解释了为什么上面的返回是返回的这个类,但是初始化操作是它的父类AbstractPipeline做的,我们来看一下

1.3 AbstractPipeline

image.png

这是AbstractPipeline的构造函数,也是这一步完成了Stream对象的创建

Stream对象

列表在进行.stream的时候是获得了一个Stream对象,对象的属性如下

image.png

像我们在使用筛选时的filter,统计时的count,转结构时的collect都在此进行了定义,具体的实现就交给了它的实现类,我们使用List的stream默认是使用的实现类ReferencePipeline,来看ReferencePipeline是怎么实现的后续处理

ReferencePipeline

collect

collect是经常使用的要进行数据格式转换的方法,看看在ReferencePipeline是怎么具体实现的

image.png

image.png