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.rhkb.cn/news/496437.html

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

相关文章

fisco-bcos系统架构

系统架构 整体架构 标签&#xff1a;架构 强扩展性 模块设计 整体架构上&#xff0c;FISCO BCOS划分成基础层、核心层、管理层和接口层&#xff1a; 基础层:提供区块链的基础数据结构和算法库 核心层: 实现了区块链的核心逻辑&#xff0c;核心层分为两大部分&#xff1a…

探秘仓颉编程语言:使用体验与功能剖析

目录 一、引言&#xff1a;仓颉登场&#xff0c;编程新纪元开启 二、初体验&#xff1a;搭建环境与 “Hello World” &#xff08;一&#xff09;环境搭建指南 &#xff08;二&#xff09;Hello World 初印象 三、核心特性剖析&#xff1a;智能、高效、安全多维解读 &…

Java 面试合集(2024版)

种自己的花&#xff0c;爱自己的宇宙 目录 第一章-Java基础篇 1、你是怎样理解OOP面向对象??? 难度系数&#xff1a;? 2、重载与重写区别??? 难度系数&#xff1a;? 3、接口与抽象类的区别??? 难度系数&#xff1a;? 4、深拷贝与浅拷贝的理解??? 难度系数&…

指针与数组:深入C语言的内存操作艺术

数组名的理解 在上⼀个章节我们在使⽤指针访问数组的内容时&#xff0c;有这样的代码&#xff1a; int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0]; 这⾥我们使⽤ &arr[0] 的⽅式拿到了数组…

使用RabbitMQ

一、MQ是什么 MQ全称 Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信&#xff0c;主要功能业务解耦。 二、市面上常见的MQ产品 RabbitMQ、RocketMQ&#xff08;阿里的&#xff09;、Kafka 、…

大模型的实践应用33-关于大模型中的Qwen2与Llama3具体架构的差异全解析

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用33-关于大模型中的Qwen2与Llama3具体架构的差异全解析。Qwen2模型与Llama3模型在架构上存在一些细微的差异,这些差异主要体现在注意力机制、模型尺寸相关参数以及嵌入层处理等方面。以下是对这些差异的详细分析。 文章…

NAT 技术如何解决 IP 地址短缺问题?

NAT 技术如何解决 IP 地址短缺问题&#xff1f; 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 随着互联网的普及和发展&#xff0c;IP 地址的需求量迅速增加。尤其是 IPv4 地址&…

kafka的备份策略:从备份到恢复

文章目录 一、全量备份二、增量备份三、全量恢复四、增量恢复 前言&#xff1a;Kafka的备份的单元是partition&#xff0c;也就是每个partition都都会有leader partiton和follow partiton。其中leader partition是用来进行和producer进行写交互&#xff0c;follow从leader副本进…

使用sam进行零样本、零学习的分割实践

参照&#xff1a;利用SAM实现自动标注_sam标注-CSDN博客&#xff0c;以及SAM&#xff08;分割一切模型&#xff09;的简单调用_sam使用-CSDN博客 sam简介&#xff1a; Segment Anything Model&#xff08;SAM&#xff09;是Meta公司于2023年发布的一种AI模型&#xff0c;它打破…

【Git】—— 使用git操作远程仓库(gitee)

目录 一、远程仓库常用命令 1、从远程仓库克隆项目 2、查看关联的远程仓库 3、添加关联的远程仓库 4、移除关联的远程仓库 5、将本地仓库推送到远程仓库 6、从远程仓库拉取项目 二、分支命令 1、查询分支 2、创建分支 3、切换分支 4、推送到远程分支 5、合并分支 …

攻防世界web新手第五题supersqli

这是题目&#xff0c;题目看起来像是sql注入的题&#xff0c;先试一下最常规的&#xff0c;输入1&#xff0c;回显正常 输入1‘&#xff0c;显示错误 尝试加上注释符号#或者–或者%23&#xff08;注释掉后面语句&#xff0c;使1后面的单引号与前面的单引号成功匹配就不会报错…

【MySQL】SQL 优化经验

1. 表的设计优化 参考依据&#xff1a;参考阿里开发手册嵩山版&#xff0c;其中有很多关于MySQL表设计的内容。类型选择&#xff1a;根据存储内容选择合适类型&#xff0c;如数值存储可选tinyint、bigint等&#xff0c;字符串可选varchar或text&#xff0c;根据内容长短选择合…

使用 .NET 6 或 .NET 8 上传大文件

如果您正在使用 .NET 6&#xff0c;并且它拒绝上传大文件&#xff0c;那么本文适合您。 我分享了一些处理大文件时需要牢记的建议&#xff0c;以及如何根据我们的需求配置我们的服务&#xff0c;并提供无限制的服务。 本文与 https://blog.csdn.net/hefeng_aspnet/arti…

STM32使用UART发送字符串与printf输出重定向

首先我们先看STM32F103C8T6的电路图 由图可知&#xff0c;其PA9和PA10引脚分别为UART的TX和RX(注意&#xff1a;这个电路图是错误的&#xff0c;应该是PA9是X而PA9是RX&#xff0c;我们看下图的官方文件可以看出)&#xff0c;那么接下来我们应该找到该引脚的定义是什么&#xf…

转运机器人推动制造业智能化转型升级

​在当今制造业智能化转型的浪潮中&#xff0c;技术创新成为企业脱颖而出的关键。富唯转运机器人凭借一系列先进技术&#xff0c;成为智能转型的卓越之选。 一体化 AMR 控制系统是富唯的一大亮点。它采用低代码流程搭建和配置模式&#xff0c;极大地缩短了部署时间。企业无需耗…

深度分析java 使用 proguard 如何解析混淆后的堆栈

经过proguard混淆过后&#xff0c;发生异常时堆栈也进行了混淆&#xff0c;那么如果获取的原始的堆栈呢&#xff1f;我们下面来看下 使用proguard 根据mapping文件直接解析 import proguard.obfuscate.MappingReader; import proguard.retrace.FrameInfo; import proguard.re…

基于JAVA+SpringBoot+Vue的影院订票系统

基于JAVASpringBootVue的影院订票系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#x1f345; 哈喽兄…

LeetCode 83 :删除排链表中的重复元素

题目&#xff1a; 地址&#xff1a;https://leetcode.cn/problems/remove-duplicates-from-sorted-list/ 方法一&#xff1a; 方法二&#xff1a; package com.zy.leetcode.LeetCode_04;/*** Author: zy* Date: 2024-12-25-15:19* Description: 删除排链表中的里复元素* …

金仓数据库-用户与角色对象权限访问的查看

数据库用户 创建用户 创建用户且设置密码 create user user01 password 123;\du 查看用户user01&#xff0c;可以看见创建成功 创建用户设置密码和不可继承 create user02 password 123 noinherit;修改用户的属性 设置用户的连接数 设置为1个 alter user user01 connect…