Java8 Stream 的核心秘密

news2024/12/24 23:15:15

小伙伴们好呀,我是 4ye,今天来分享下 Java8 Stream 的源码

核心回顾

  1. stream 是一次性的,不是数据结构,不存储数据,不改变源数据.。
  2. API 分为终端和中间操作,中间操作是惰性的,碰到终端才去执行。
  3. 中间操作有无状态和有状态之分,有状态需要更改上一步操作获得的所有元素,才可以进行下一步操作,比如 排序 sorted,去重 distinct,跳过 skip,限制 limit 这四个,需要多迭代一次。
  4. 终端操作有短路与否之分,短路操作有 anyMatch, allMatch, noneMatch, findFirst, findAny

整体概览

这里列出一些重要的类,是看源码过程中必须了解的。

比如 :

  • Sink 接口是数据实际操作的地方,核心方法: begin,accept,end
  • AbstractPipeline 抽象类是核心的数据结构,双链表

demo代码

这里沿用上文的例子

        Student aStud = new Student(1, "a");
        Student bStud = new Student(2, "b");
        Student cStud = new Student(3, null);
​
//         集合的创建 一
        List<Student> collect1 = Stream.of(aStud, bStud, cStud).collect(Collectors.toList());
        collect1.forEach(System.out::println);
​
        List<String> studNameList = studentList.stream()
                .map(Student::getName)
                .filter(Objects::nonNull)
                .map(String::toUpperCase)
                .sorted()
                .map(e -> e + "c")
                .collect(Collectors.toList());
复制代码

步骤解析

都在这里了 👇

这里步骤太多了,就不一一放出来了 ,列下核心

  1. wrapSink, 创建 Sink 链,将管道的 Sink 操作连接在一起
  2. copyInto , 处理数据

wrapSink()

开始套娃,从 ReducingSink 往前套

opWarpSink 方法调用的是每一步 中间操作 中的方法

通过 单链表 的形式将他们联系在一起

Sink 链创建结果

copyInto()

这里判断是不是 短路操作 ,然后就去执行 Sink 的 begin,accept,end 方法。

通过 forEachRemaining 进行内部迭代,这个是 Spliterator 的方法。

map 链节点,直接调用传进来的方法,

filter 链节点,多一步判断

sorted 节点,添加到 list 中。

注意,此时没有继续调用 downstream.accept 方法!

意味着,我们代码中的 5 个中间步骤只执行了前 3 个。

不过别担心, sorted 链节点中它重写了这个 end,并开启对新数据的新一轮遍历

这就是我们提到的,有状态中间操作多一次迭代的原因

最后呢,是来到终止操作 TerminalOp 中的 accept,这里执行的是 list 的 add 方法(我们调用 Collectors.toList() 中构建的),至此,数据添加到 state 中

获取数据,ReducingSink 继承了 Box 这个抽象类,最后 get 方法得到结果。

总结

代码对应的执行流程👇

  1. 先创建流,出现了 Head 节点

  2. 创建中间管道 Pipeline

  3. 调用终端操作后有三步 👇

    (一)将中间管道的 Sink 操作连接在一起 (wrapSink) (二)处理数据 (copyInto),主要调用 Sink 中的 begin,accept(核心),end 操作 (三)返回结果,ReducingSink 中的 get 方法

主要记住这个 wrapSink 方法 和 copyInto 方法。

一个套娃,一个调用 begin,accept,end 等方法。

那么,这个 stream 的原理机制就出来了:

利用 wrapSink 方法将各个中间操作中的 Sink 嵌套在一起,然后来到 copyInto 方法,调用 begin 通知各个 Sink 做好准备,接着进行内部迭代调用 accept 方法,再调用 end 方法完成数据的操作,最后通过 get 方法,获取新容器中的数据,便是结果了。

此外,源码的 链式调用API 写法设计模式 的使用以及 泛型四大函数式接口 组合构建的高度抽象,封装写法,对我们的编码能力,源码阅读能力也有很大的帮助!

比如 这个 Consumer+Function 接口的组合,配合泛型上下限的使用

源码中 访问者模式工厂模式 等设计模式的影子

访问者模式: 将数据结构与数据操作分离

对应源码:数据结构是 Pipeline ,操作是 Sink

对 stream 的特点更加熟悉

比如:

  1. stream 是一次性的,不是数据结构,不存储数据,不改变源数据.。
  2. 中间操作是惰性的,遇到 终端操作才真正执行
  3. 有状态的中间操作的特殊之处在于多迭代一次
  4. 内部迭代
  5. 终端操作主要做了两件事,串连中间操作,调用 accept 方法处理数据

当然这里我也只测试了 非短路模式,短路模式又是怎样设计的呢,小伙伴们可以自己上手 debug 下,加深印象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/22107.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python自动化测试

测试软件&#xff1a;pycharm 解释器版本&#xff1a;3.10.7 测试浏览器&#xff1a;谷歌 或 edge 谷歌web驱动下载地址&#xff1a;chromedriver.storage.googleapis.com/index.html edgeweb驱动下载地址&#xff1a;Microsoft Edge WebDriver - Microsoft Edge Developer 第一…

免费查题接口系统后台

免费查题接口系统后台 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点…

零基础自学javase黑马课程第十三天

零基础自学javase黑马课程第十三天 ✨欢迎关注&#x1f5b1;点赞&#x1f380;收藏⭐留言✒ &#x1f52e;本文由京与旧铺原创&#xff0c;csdn首发&#xff01; &#x1f618;系列专栏&#xff1a;java学习 &#x1f4bb;首发时间&#xff1a;&#x1f39e;2022年11月7日&…

springboot视图渲染技术

目录 一、Freemarker简介及入门 二、Freemarker语法 1、取值 1.1默认值 1.2 对null值进行判断 2、条件 3、循环 4、include 5、 局部变量(assign)/全局变量(global) 一、Freemarker简介及入门 学习网址&#xff1a;什么是 FreeMarker? - FreeMarker 中文官方参考手册 …

2022强网拟态pwn-webheap

2022强网拟态pwn-webheap 这题的逻辑是一开始笔者硬逆给逆出来了&#xff0c;但是后面在Ex师傅的点播下成功的在github上找到了这个的原生项目 https://github.com/google/libnop 在审计的过程中发现了至关重要的信息&#xff0c;发现和逆向的格式一样的东西&#xff0c;就是…

BCN-PEG2-Mal,BCN-OH,endo-BCN-PEG2-BiotinBCN几种衍生物的特点

BCN-PEG 是一类具有双环[6.1.0]壬炔的 PEG 接头。它用于叠氮化物反应性无铜点击化学。BCN在没有催化剂的情况下很容易与叠氮官能化化合物或生物分子反应形成稳定的三唑键&#xff0c;PEG间隔物增加了所得化合物的水溶性。今天这一章西安凯新生物科技有限公司​主要为大家分享BC…

多段曲线控温从Simulink仿真到PLC控制实现

多段曲线温度控制,专栏有系列文章和完整源代码,大家可以自行搜索。链接如下: 博途PLC 1200/1500PLC多段曲线控温FB(支持40段控温曲线、段曲线搜索、暂停、跳段等功能)_RXXW_Dor的博客-CSDN博客多段控温曲线之前专栏的其它文章也有所讲解,大家可以参看下面这篇专栏博途1200…

Get CLI - 强大的项目管理 GetX 工具

Get CLI - 强大的项目管理 GetX 工具 https://shirsh94.medium.com/get-cli-powerful-getx-tool-for-project-management-bdf54572d91f 前言 一个来自 Getx 的工具可以帮助你快速的建立项目&#xff0c;页面和视图。 大家好&#xff0c;在本文中&#xff0c;我将讨论 get CLI 工…

PTA题目 奇偶分家

给定N个正整数&#xff0c;请统计奇数和偶数各有多少个&#xff1f; 输入格式&#xff1a; 输入第一行给出一个正整N&#xff08;≤1000&#xff09;&#xff1b;第2行给出N个非负整数&#xff0c;以空格分隔。 输出格式&#xff1a; 在一行中先后输出奇数的个数、偶数的个…

深度学习中常见概念(收敛、优化器、学习率等)

收敛 打个简单的比方&#xff0c;训练网络模型&#xff0c;就好比解方程&#xff0c;为了得到这个方程的极值点&#xff0c;训练的过程就好比是找准一个方向&#xff0c;不断的朝这个方向靠近,使得方程的值不断减小&#xff0c;最终达到极值点&#xff0c;而不收敛&#xff0c…

微型计算机基础(常用术语,总线,系统组成)

目录 微型计算机常用术语 计算机系统 基本组成图​编辑 Cache&#xff08;内存和CPU之间&#xff09; 虚存&#xff08;内存和外存之间 &#xff09; CPU是微机的核心部件&#xff0c;具有运算和控制功能 总线 数据中线DB&#xff08;Data Bus&#xff09; &#xff0…

kubernetes集群配置默认存储类(nfs)

文章目录概述安装nfs服务端node节点上安装启动nfs配置StorageClass创建Deployment创建ServiceAccount创建StorageClass对象创建资源对象常见问题参考文档概述 StorageClass 为管理员提供了描述存储 “类” 的方法。 不同的类型可能会映射到不同的服务质量等级或备份策略&#x…

钙通道阻滞剂/拮抗剂的应用 | MedChemExpress

我们都知道钙、钾、钠离子对于维持个体内环境的重要性&#xff0c;离子通道一直是个有趣而复杂的话题。它们就像为某种物质专属定制的“门”或 VIP 通道&#xff0c;不仅分类繁多&#xff0c;还有着严密的“门控”机制。每个细胞都像一个电池&#xff0c;正常状态下&#xff0c…

SpringBoot SpringBoot 开发实用篇 5 整合第三方技术 5.10 jetcache 本地缓存方案

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇5 整合第三方技术5.10 jetcache 本地缓存方案5.10.1 使用 jetcache 实…

【Java高级】一篇文章带你学会什么是注解

目录 注解概述 | Java内置的三个注解 Deprecated Override SuppressWarnings | 元注解 Target Retention&#xff08;注解生命周期&#xff09; Documented Inherited Repeatable&#xff08;JDK1.8&#xff09; | 自定义注解 自定义注解的概述 自定义注解的步骤…

货币政策传导与货币政策调控-中国视角下的宏观经济

货币政策传导与货币政策调控-潘登同学的宏观经济学笔记 文章目录货币政策传导与货币政策调控-潘登同学的宏观经济学笔记货币传导路径货币是银行的负债——货币的“形而下”定义贷款创造存款货币乘数货币就是记忆&#xff08;money is memory&#xff09;——货币的“形而上”定…

libevent库

libevent介绍 1 事件驱动, 高性能, 轻量级, 专注于网络 2 源代码精炼, 易读 3 跨平台 4 支持多种I/O多路复用技术, 如epoll select poll等 5 支持I/O和信号等事件 libevent的核心实现: 在linux上, 其实质就是epoll反应堆. libevent是事件驱动, epoll反应堆也是事件驱动, 当要…

硬件基础 -- D/A数字模拟信号

D/A 需要数位模拟开关 如果开关打卡&#xff0c;则此位电压参与运算 如果开关关闭&#xff0c;则此位电压0V参与运算 转换过程中需要将数字数字量锁存 转换过程 模拟量转数字量需要比较器 数字量转模拟量需要运放 #mermaid-svg-wJVhc3DQ619gtYuZ {font-family:"trebuchet …

【计算机毕业设计】6.超市仓库管理系统+vue

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 基于B/S的超市进销存管理系统的设计与实现 摘 要&#xff1a;开发本超市进销存管理系统的主要目标是方便企业对商品、客户和员工信息的实时掌控&#xff0c;提高企业的工作效率。本系统是采用java开发的一个基于B/S…

渗透测试——基于SQL注入拿到webshell

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座右…