Java Stream流详解——串行版

Stream流——串行版

​ Stream流是java8引入的特性,极大的方便了我们对于程序内数据的操作,提高了性能。通过函数式编程解决复杂问题。

1.BaseStream<T,S extense BaseStream<T,S>>

​ 他是流处理的基石概念,重点不在于这个接口定义了什么方法,而是它独特的参数类型。
首先约定好:T——入参类型 S——出参类型
S是继承于自己的同样的类型,从而形成一种递归,每一次返回的结果类型都是自己或它的子类。这样做是因为我们在流处理时,不会在原有的流上进行操作,而是形成新的流返回会去。这样设计免去了类型转换出错和增强了灵活性

2.Stream extends BaseStream<T, Stream>

BaseStream有4大子类,我们讲一个使用范围最广的——Stream
它定义了我们常用的一些方法如
Stream filter (Predicate<? super T> predicate)
这里的Predicate就是一个函数式例如判断对象是否为空 s->s!=null

中间操作 (Intermediate operations)

无状态 (Stateless)有状态 (Stateful)
unordered()distinct() 去重
filter() 过滤元素sorted() 排序
map() 转换元素类型limit()
mapToInt()skip() 跳过前n个元素
mapToLong()
mapToDouble()
flatMap()
flatMapToInt()
flatMapToLong()
flatMapToDouble()
peek()

结束操作 (Terminal operations)

非短路操作短路操作 (short-circuiting)
forEach()anyMatch()
forEachOrdered()allMatch()
toArray()noneMatch()
reduce() 归约findFirst()
collect()findAny()
max()
min()
count()

咱们这里通过它的一个实现类ReferencePipeline来举个例子来体验一下

List<Integer> numbers = Arrays.asList(2, 1, 3, 8, 5, 6, 7, 4, 9, 10);
List<String> evenNumbers = numbers.stream().map(o->o.toString())//将元素转为字符串.filter(n -> n.length() == 1)//剔除大于两位数的元素.sorted()//排序.collect(Collectors.toList());//整合出一个新的流返回System.out.println(evenNumbers);

先定义了一个List,通过.stream()新建一个流管道,函数式编程的好处就是他可以把操作整合到一起,这里的 o->o.toString()和n->n.length()==1会被Java整合为
(o -> o.toString()) -> (n -> n.length() == 1)一个操作链
接下来,您是否好奇这个链条是如何组装的,反正我很好奇,let's dive into water

3.ReferencePipeline

在这里插入图片描述

它继承了AbstractPipeline,而在其中保存了三个引用,类型都是自己,分别是sourceStage指向第一个Sink(后续展开),接下来就是previousStage和nextStage分别链接上下Sink。
下图给出了具体的流程
在这里插入图片描述

中间操作是一种烂加载处理,只有当触发了collect()方法才会真正的调用每个Steam流中的wrapSink方法去处理数据。之后调用sort()进行排序。我们来具体看一个方法是如何处理的

 public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {Objects.requireNonNull(mapper);return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {@OverrideSink<P_OUT> opWrapSink(int flags, Sink<R> sink) {return new Sink.ChainedReference<P_OUT, R>(sink) {@Overridepublic void accept(P_OUT u) {downstream.accept(mapper.apply(u));

在ReferencePipeline中它定义三个静态内部类——StatelessOp,StatafulOp,Head。先是对函数式判空,然后返回一个无状态流。关键在于它内部定义的opWrapSinlk通过返回一个Sink类并在其中定义了具体的操作accept()。然后调用函数式,并通过accept()触发下游Stream进行进一步处理。

4.Sink

抽象的来讲,上面所说的ReferencePipeline就像是流水线上不停流动的传输带,而真正在加工物品的就是我们的Sink类

在这里插入图片描述

这里的Consumer接口就是我们将不同的流处理函数式拼接起来的关键

public interface Consumer<T> {void accept(T t);default Consumer<T> andThen(Consumer<? super T> after) {Objects.requireNonNull(after);return (T t) -> { accept(t); after.accept(t); };}
}

andThen()方法,首先是自己调用自己的accept(),再调用下游的accept()
像我们前面写到的例子,map(o->o.toString)和filter(n->n.length)中的参数就是一个Consumer

5.归约

我们将最后一步collect()定义为归约,将流中的所有元素归约为一个最终的结果。
它通过操作一个Collector进行操作,包含三个步骤
累加(accumulation):将流中的每个元素依次累加到一个容器中。
合并(combining):如果存在并行流,多个部分的结果需要合并。
完成(finishing):在所有元素处理完后,生成最终的结果。

public interface Collector<T, A, R> {Supplier<A> supplier(); // 提供一个容器,容器类型是 ABiConsumer<A, T> accumulator(); // 累加器,负责将元素添加到容器BinaryOperator<A> combiner(); // 合并器,用于并行处理时合并多个容器Function<A, R> finisher(); // 结果转换器,返回最终的结果Set<Collector.Characteristics> characteristics(); // 一些特征,指示这个 Collector 是否具有某些优化特性
}

例如我们最常用的toList()将流中的所有元素收集到一个Lsit中。

 public static <T>Collector<T, ?, List<T>> toList() {return new CollectorImpl<>(ArrayList::new, List::add,(left, right) -> { left.addAll(right); return left; },CH_ID);}

ArrayList::new,返回一个List容器,通过List::add方法添加进入容器,后续处理并行流。

以下是关于 Java Stream API 中 collect 归约操作的表格,其中总结了常见的归约操作、作用说明及示例:

归约操作作用说明示例代码
toList()将流中的元素收集到一个 List 中。List<String> result = names.stream().collect(Collectors.toList());
toSet()将流中的元素收集到一个 Set 中,自动去重。Set<String> result = names.stream().collect(Collectors.toSet());
joining()将流中的元素连接成一个字符串,支持指定分隔符、前缀和后缀。String result = names.stream().collect(Collectors.joining(", ", "[", "]"));
groupingBy()根据某个条件将流中的元素分组,返回一个 MapMap<Integer, List<String>> groupedByLength = names.stream().collect(Collectors.groupingBy(String::length));
partitioningBy()将流中的元素分成两组,通常用于二元分类。Map<Boolean, List<String>> partitioned = names.stream().collect(Collectors.partitioningBy(name -> name.length() > 3));
summarizingInt()对流中的元素进行统计,返回 IntSummaryStatistics,包括计数、求和、最小值、最大值、平均值等。IntSummaryStatistics stats = names.stream().collect(Collectors.summarizingInt(String::length));
reducing()对流中的元素进行归约操作(例如累加、求最大值等),返回一个单一结果。Optional<String> result = names.stream().collect(Collectors.reducing((s1, s2) -> s1.length() > s2.length() ? s1 : s2));
toMap()将流中的元素根据某个键值映射规则收集到一个 Map 中。Map<Integer, String> map = names.stream().collect(Collectors.toMap(String::length, name -> name));
   | 将流中的元素根据某个键值映射规则收集到一个 `Map` 中。        | `Map<Integer, String> map = names.stream().collect(Collectors.toMap(String::length, name -> name));` |

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

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

相关文章

el-backtop(返回顶部)

案例&#xff1a; <el-backtop target".app-main"><svg-icon icon-class"backtop" size"24px" /></el-backtop>

探秘“香水的 ChatGPT”:AI 开启嗅觉奇幻之旅!

你没有看错&#xff0c;AI也能闻到味道了&#xff01;这是一家名为Osmo公司公布的信息&#xff0c;他们成功创造出了由AI生成的李子味道&#xff0c;快跟着小编一探究竟吧~ 【图片来源于网络&#xff0c;侵删】 Osmo公司的这项技术&#xff0c;通过分析香味的化学成分和人类嗅…

Vue3入门(9)

1. 【 replace属性】 作用&#xff1a;控制路由跳转时操作浏览器历史记录的模式。 浏览器的历史记录有两种写入方式&#xff1a;分别为push和replace&#xff1a; - push是追加历史记录&#xff08;默认值&#xff09;。 - replace是替换当前记录。 . 开启replace模式&#xff…

第十九章 C++ 日期 时间

C 日期 & 时间 C 标准库没有提供所谓的日期类型。C 继承了 C 语言用于日期和时间操作的结构和函数。为了使用日期和时间相关的函数和结构&#xff0c;需要在 C 程序中引用 <ctime> 头文件。 有四个与时间相关的类型&#xff1a;clock_t、time_t、size_t 和 tm。类型…

电子配件行业的未来之路:产品说明书数字化转型的力量

在科技飞速发展的今天&#xff0c;电子配件行业作为科技创新的前沿阵地&#xff0c;正经历着前所未有的变革。从智能手机、平板电脑到智能穿戴设备&#xff0c;各种新型电子配件层出不穷&#xff0c;极大地丰富了人们的生活。然而&#xff0c;随着产品种类的增多和功能的复杂化…

强化学习方法分类详解

强化学习方法分类详解 引言 强化学习&#xff08;Reinforcement Learning, RL&#xff09;是一种通过智能体与环境互动来学习如何做出最佳决策的方法。根据不同的优化中心、策略特性、环境模型、奖励函数、动作空间类型以及行为策略和目标策略的一致性&#xff0c;RL可以分为…

RockyLinux介绍及初始化

文章目录 一、背景二、下载 RockyLinux9 镜像三、环境初始化四、安装 Docker 环境 一、背景 这里讲一个小故事&#xff1a; 我们都知道Linux 内核是由芬兰计算机科学家林纳斯托瓦兹 (Linus Torvalds) 于 1991 年首次开发的&#xff0c;随后有一个非常重要的公司RetHat成立&am…

AWS、Google Cloud Platform (GCP)、Microsoft Azure、Linode和 桔子数据 的 价格对比

要对比 AWS、Google Cloud Platform (GCP)、Microsoft Azure、Linode 和 桔子数据 的 价格&#xff0c;我们需要先了解每个平台的定价模型、服务类型以及不同服务之间的价格差异。以下是根据各个平台常见服务&#xff08;如计算实例、存储、数据传输等&#xff09;做的一个 简化…

OpenCV相机标定与3D重建(36)计算两幅图像之间基本矩阵(Fundamental Matrix)的函数findFundamentalMat()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 从两幅图像中的对应点计算基本矩阵。 cv::findFundamentalMat 是 OpenCV 中用于计算两幅图像之间基本矩阵&#xff08;Fundamental Matrix&#…

Vscode + gdbserver远程调试开发板指南:

本章目录 步骤环境准备网络配置vscode配置步骤 (全图示例)开发板配置开始调试注意: 每次断开之后&#xff0c;开发板都需要重新启动gdbserver才可调试。 参考链接: 步骤 环境准备 将交叉编译链路径加入$PATH变量&#xff1a;确保系统能够找到所需的工具。 export PATH$PATH:/p…

对外发PDF设置打开次数

在线 Host PDF 文件并对链接进行限制——保障文件安全的最佳解决方案 在数字化办公和远程协作日益普及的今天&#xff0c;如何安全高效地分享 PDF 文件成为许多用户关注的重点。MaiPDF 作为一款功能强大的在线工具&#xff0c;不仅支持在线 host PDF 文件&#xff0c;还提供多…

VS2022 中的 /MT /MTd /MD /MDd 选项

我们有时编译时,需要配置这个 运行库,指定C/C++运行时库的链接方式。 如下图 那么这些选项的含义是什么? /MT:静态链接多线程库 /MT选项代表“Multi-threaded Static”,即多线程静态库。选择此选项时,编译器会从运行时库中选择多线程静态连接库来解释程序中的代码,…

MacOS下TestHubo安装配置指南

TestHubo是一款开源免费的测试管理工具&#xff0c; 下面介绍MacOS私有部署的安装与配置。TestHubo 私有部署版本更适合有严格数据安全要求的企业&#xff0c;支持在本地或专属服务器上运行&#xff0c;以实现对数据和系统的完全控制。 1、Mac 服务端安装 Mac安装包下载地址&a…

Windows 11 配置gym、mujoco、mujoco-py环境教程

Windows 11 配置gym、mujoco、mujoco-py环境教程 整理了windows11系统安装mujoco、mujoco_py、gym的教程以及报错解决方法。 环境版本 mujoco-py-2.1.2.14 mujoco210 gym==0.23.1 python 3.9.16 pytorch 1.12.1+cu113 mujoco安装 1. 在Github中下载mujoco210压缩包 G…

Java重要面试名词整理(五):Redis

文章目录 Redis高级命令Redis持久化RDB快照&#xff08;snapshot&#xff09;**AOF&#xff08;append-only file&#xff09;****Redis 4.0 混合持久化** 管道&#xff08;Pipeline&#xff09;**StringRedisTemplate与RedisTemplate详解**Redis集群方案gossip脑裂 Redis LuaR…

Amazon Bedrock 实践 - 利用 Llama 3.2 模型分析全球糖尿病趋势

黄浩文 资深开发者布道师 亚马逊云科技 拥有电信、互联网以及云计算等行业超过 20 年的丰富经验&#xff0c;曾任职于微软、Sun 和中国电信。他目前专注于生成式 AI、大型语言模型 (LLM)、机器学习和数据科学等领域的技术内容创作和实践分享&#xff0c;致力于赋能全球开发者。…

期权懂|如何计算期权卖方平仓后的盈利?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 如何计算期权卖方平仓后的盈利&#xff1f; 期权卖方平仓后的盈利计算涉及多个因素&#xff0c;包括期权的交易价格、平仓价格以及权利金的变动等。 交易价格&#xff1a;期权卖…

【连续学习之VCL算法】2017年论文:Variational continual learning

1 介绍 年份&#xff1a;2017 期刊&#xff1a; arXiv preprint Nguyen C V, Li Y, Bui T D, et al. Variational continual learning[J]. arXiv preprint arXiv:1710.10628, 2017. 本文提出的算法是变分连续学习&#xff08;Variational Continual Learning, VCL&#xf…

多视图 (Multi-view) 与多模态 (Multi-modal)

多视图 (Multi-view) 与多模态 (Multi-modal) 是两种不同的数据处理方式&#xff0c;它们在机器学习和数据分析中有着重要的应用。尽管这两者有一些相似之处&#xff0c;但它们关注的角度和处理方法有所不同。 多视图 (Multi-view) 定义&#xff1a;多视图指的是同一数据对象…

MySQL 性能瓶颈,为什么 MySQL 表的数据量不能太大?

MySQL的性能瓶颈(为什么MySQL有几万的qps,怎么来的?性能分析 为什么 MySQL 表不能太大网上大部分人的说法:问题的关键: B树层数对查询性能的影响到底有多大? 是什么导致的 MySQL 查询缓慢?如何解决: MySQL的性能瓶颈(为什么MySQL有几万的qps,怎么来的? 一个全表扫描的查询…