Stream 串行流 原理

本文详细探讨了Java Stream的出现背景、使用场景及其内部实现原理。Stream作为一种更高效的数据处理方式,解决了传统迭代存在的问题,尤其在大数据时代,其流水线般的处理模式显得尤为重要。通过Stream,开发者可以方便地对数据集合进行各种操作,如过滤、排序等。Stream的实现涉及到一系列中间操作和终止操作,其内部结构类似双向链表,节点间通过引用连接。在流水线的启动和执行过程中,数据通过Sink节点进行处理,最终由终止操作收集结果。Stream的延迟执行特性以及短路操作使其在处理大量数据时表现出优越的性能。
摘要由CSDN通过智能技术生成

Stream 为什么会出现?

Stream 出现之前,遍历一个集合最传统的做法大概是用 Iterator,或者 for 循环。这种两种方式都属于外部迭代,然而外部迭代存在着一些问题。

  • 开发者需要自己手写迭代的逻辑,虽然大部分场景迭代逻辑都是每个元素遍历一次。

  • 如果存在像排序这样的有状态的中间操作,不得不进行多次迭代。

  • 多次迭代会增加临时变量,从而导致内存的浪费。

虽然 Java 5 引入的 foreach 解决了部分问题,但也引入了新的问题。

  • foreach 遍历不能对元素进行赋值操作

  • 遍历的时候,只有当前被遍历的元素可见,其他不可见

随着大数据的兴起,传统的遍历方式已经无法满足开发者的需求。

就像小作坊发展到一定程度要变成大工厂才能满足市场需求一样。大工厂和小作坊除了规模变大、工人不多之外,最大的区别就是多了流水线。流水线可以将工人们更高效的组织起来,使得生产力有质的飞跃。

所以不安于现状的开发者们想要开发一种更便捷,更实用的特性。

  • 它可以像流水线一样来处理数据

  • 它应该兼容常用的集合

  • 它的编码应该更简洁

  • 它应该具有更高的可读性

  • 它可以提供对数据集合的常规操作

  • 它可以拼装不同的操作

经过不懈的能力,Stream 就诞生了。加上 lambda 表达式的加成,简直是如虎添翼。

你可以用 Stream 干什么?

下面以简单的需求为例,看一下 Stream 的优势:

从一列单词中选出以字母a开头的单词,按字母排序后返回前3个。

传统实现方式

List<String> list = Lists.newArrayList("are", "where", "advance", "anvato", "java", "abc");

List<String> tempList = Lists.newArrayList();

List<String> result = Lists.newArrayList();

for( int i = 0; i < list.size(); i++) {

    if (list.get(i).startsWith("a"))

        tempList.add(list.get(i));

}

tempList.sort(Comparator.naturalOrder());

result = tempList.subList(0,3);

Stream实现方式

List<String> list = Arrays.asList("are", "where", "anvato", "java", "abc");

List<String> result =

    list.stream()                //定义输入源,得到Stage0 Head节点(流)

      .filter(s -> s.startsWith("a"))   //定义中间操作,得到Stage1 StatelessOp节点(流) 

      .sorted()                //定义中间操作,得到Stage2 StatefulOp节点(流),SortedOps.OfRef实例

      .limit(3)                //定义中间操作,得到Stage3 StatefulOp节点(流),SliceOps的StatefulOp实例

      .collect(Collectors.toList());    //定义终端操作, TerminalOp节点(流),ReduceOp实例

Stream 是怎么实现的?

需要解决的问题:

  • 如何定义流水线?

  • 原料如何流入?

  • 如何让流水线上的工人将处理过的原料交给下一个工人?

  • 流水线何时开始运行?

  • 流水线何时结束运行?

总观全局

Stream 处理数据的过程可以类别成工厂的流水线。数据可以看做流水线上的原料,对数据的操作可以看做流水线上的工人对原料的操作。

事实上 Stream 只是一个接口,并没有操作的缺省实现。最主要的实现是 ReferencePipeline,而 ReferencePipeline 继承自 AbstractPipeline ,AbstractPipeline 实现了 BaseStream 接口并实现了它的方法。但 ReferencePipeline 仍然是一个抽象类,因为它并没有实现所有的抽象方法,比如 AbstractPipeline 中的 opWrapSink()抽象方法,该方法是由具体的中间操作和终端操作来实现的 。ReferencePipeline内部定义了三个静态内部类,分别是&#

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值