Java8 Stream浅析

简要梳理记录

1.什么是Stream

  1)一种支持串行和并行聚合操作的元素序列。
  2)是Java 8 API添加的一种新的抽象,称为流,以更直观的方式来提供一种对 Java 集合运算和表达的高阶抽象。
  3)通过流,可以以一种声明的方式处理数据,即关注的是“做什么而不是怎么做”。
  4)将要处理的元素集合看做一种流,在管道中传输和处理。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

2.操作符

操作符是对数据进行的一种处理工作。
Stream的操作符大体上分为两种:中间操作符终止操作符

2.1 中间操作符

1)筛选与切片

  • filter: 把不想要的数据过滤

  • skip:跳过某些元素。

  • limit: 限流操作,比如数据流中有10个 只要前3个就可以使用。
    skip 和 limit 可搭配出数据库分页效果

  • distinct:去重,通过流中元素的 hashCode() 和 equals() 去除重复元素

2)映射

  • map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。(mapToInt,mapToLong,mapToDouble)
  • flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

3)排序

  • sorted():自然排序,流中元素需实现Comparable接口
  • sorted(Comparator com):定制排序,自定义Comparator排序器

4)消费

  • peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。

2.2 终止操作符

必须有终止操作符,才会执行处理操作,否则数据不会流动起来。

  • collect:收集,Collectors提供了多种收集器。
  • count: 统计操作,统计最终的数据个数。
  • findFirst:查找第一个。
  • findAny: 查找任何一个 。
  • noneMatch、allMatch、anyMatch 匹配操作,数据流中是否存在符合条件的元素 返回值为bool 值。
  • min、max 最值操作,需要自定义比较器,返回数据流中最大最小的值。
  • reduce 规约操作,将整个数据流的值规约为一个值,count、min、max底层就是使用reduce。
  • forEach、forEachOrdered 遍历操作,这里就是对最终的数据进行消费了。
  • toArray 数组操作,将数据流的元素转换成数组。

这篇博文中有详细的demo
https://www.jianshu.com/p/11c925cdba50

3.Stream实现核心逻辑

3.1 核心类的职责

BaseStream:规定了流的基本接口,比如iterator、spliterator、isParallel等;
Stream:定义了map、filter、flatmap等用户关注的常用操作;
PipelineHelper:主要用于Stream执行过程中相关结构的构建;
AbstractPipeline:流水线构成(双向链表),直接实现类为ReferencePipeline,
Head、StatelessOp、StatefulOp为ReferencePipeline中的内部类。
Stage:每一个stage就是一个AbstractPipeline的实例,每个Stage都记录了前一个Stage和本次的操作以及回调函数,依靠这种结构就能建立起对数据源的所有操作。
Sink接口: 定义了 Stream 之间的操作行为,包含 begin()、end()、cancellationRequested()、accpt()四个方法。

3.2 执行流程
示例代码:

 List<String> names = Arrays.asList("kotlin", "java", "go");
 int maxLength = names.stream().filter(name -> name.length() <= 4).map(String::length).max(Comparator.naturalOrder()).orElse(-1);

1)加载数据源:StreamSupport 类中的 stream 方法,初始化一个 ReferencePipeline的 Head 内部类对象。
2)中间操作:中间操作通过AbstractPipeline 生成一个中间操作 Stage 链表
在这里插入图片描述
中间操作例如filter、map等会返回一个新的StatelessOp对像。
StatelessOp:无状态中间操作 StatefulOp:有状态操作
3)终结操作
触发之前的中间操作,从最后一个Stage开始,递归产生一个Sink链。
opWrapSink会返回一个新的sink,然后再递归传入sink。在这里插入图片描述wrapAndCopyInto 生成 Sink 链表后,会通过 copyInfo 方法执行 Sink 链表的具体操作。
在这里插入图片描述
并行处理:使用ForkJoin 框架,对 Stream 处理进行分片。具体逻辑根据evaluateParallel方法查看。

3.3 处理逻辑
1)每一个操作如何记录
使用satge记录每次操作。一个完整的操作是由数据来源、操作、回调函数组成的三元组来表示
2)如何叠加
每一步操作使用satge记录后并没有执行。Sink接口,包括begin()、end()、cancellationRequested()、accept()。中间操作的子类中包含一个指向下游sink的指针。
3)如何执行
每个节点形成stage链,最终会触发从最后一个stage开始执行。
4)链表形成
stage链(AbstractPipeline链):每个中间操作会创建一个新的stage,并维护previousStage属性,最终形成链表,stage链表是个双链表,有pre和next指针。
sink链:递归调用,维护每个downstream属性。

https://juejin.cn/post/6901936973791887368

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值