当前位置: 首页 > news >正文

Java基础 - Stream 流:Stream API的终端操作

在前两篇博客中,我介绍了构建 Stream 流的多种方式,以及 Stream API 的中间操作,如果你还没有阅读,你可以点击这里和这里查看。

Java基础 - Stream 流:构建流的多种方式

Java基础 - Stream 流:Stream API的中间操作

在这篇博客中,我将探索 Stream API 的终端操作,它们可以让你从 Stream 流中得到最终的结果,或者产生一些副作用。

Stream API 的终端操作是指那些会消耗 Stream 流,产生一个最终的结果或者一个副作用的操作,它们不能再链式地调用,而是结束一个操作管道。Stream API 提供了很多终端操作,可以分为以下几类:

  • 归约:这类操作可以让你将 Stream 流中的所有元素合并为一个值,例如 reduce, sum, max, min, count 等。
  • 收集:这类操作可以让你将 Stream 流中的所有元素收集到一个集合或者一个值中,例如 collect, toList, toSet, toMap, joining 等。
  • 遍历:这类操作可以让你对 Stream 流中的每个元素执行一个消费者(Consumer)操作,例如 forEach, forEachOrdered 等。
  • 匹配:这类操作可以让你判断 Stream 流中的元素是否满足一个条件,例如 anyMatch, allMatch, noneMatch 等。
  • 查找:这类操作可以让你从 Stream 流中找到一个元素,例如 findAny, findFirst 等。

下面,我将用一些示例来展示这些终端操作的用法和效果。

1. 归约

1.1 reduce

reduce 操作可以让你将 Stream 流中的所有元素按照一个二元操作(BinaryOperator)进行归约,返回一个 Optional 对象,它可能包含一个值,也可能为空。你也可以指定一个初始值,作为归约的起点。例如:

// 创建一个 Stream 流对象
Stream<Integer> numberStream = Stream.of(1, 2, 3, 4, 5);// 使用 reduce 操作将所有元素相加,不指定初始值
Optional<Integer> sum1 = numberStream.reduce((a, b) -> a + b);// 输出 Optional[15]
System.out.println(sum1);// 使用 reduce 操作将所有元素相加,指定初始值为 0
int sum2 = numberStream.reduce(0, (a, b) -> a + b);// 输出 15
System.out.println(sum2);

1.2 sum

sum 操作可以让你将 Stream 流中的所有元素相加,返回一个数值。你需要将 Stream 流转换为数值流,例如 IntStream, LongStream, DoubleStream 等。例如:

// 创建一个 Stream 流对象
Stream<Integer> numberStream = Stream.of(1, 2, 3, 4, 5);// 使用 sum 操作将所有元素相加,需要转换为 IntStream
int sum = numberStream.mapToInt(Integer::intValue).sum();// 输出 15
System.out.println(sum);

1.3 max

max 操作可以让你从 Stream 流中找到最大的元素,返回一个 Optional 对象,它可能包含一个值,也可能为空。你可以指定一个比较器(Comparator)来定义元素的大小。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 max 操作找到最大的元素,按照自然顺序比较
Optional<String> max1 = animalStream.max(String::compareTo);// 输出 Optional[yellow]
System.out.println(max1);// 使用 max 操作找到最大的元素,按照长度比较
Optional<String> max2 = animalStream.max((s1, s2) -> s1.length() - s2.length());// 输出 Optional[elephant]
System.out.println(max2);

1.4 min

min 操作可以让你从 Stream 流中找到最小的元素,返回一个 Optional 对象,它可能包含一个值,也可能为空。你可以指定一个比较器(Comparator)来定义元素的大小。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 min 操作找到最小的元素,按照自然顺序比较
Optional<String> min1 = animalStream.min(String::compareTo);// 输出 Optional[cat]
System.out.println(min1);// 使用 min 操作找到最小的元素,按照长度比较
Optional<String> min2 = animalStream.min((s1, s2) -> s1.length() - s2.length());// 输出 Optional[cat] 或者 Optional[dog] 或者 Optional[fox]
System.out.println(min2);

1.5 count

count 操作可以让你计算 Stream 流中的元素个数,返回一个长整型。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 count 操作计算元素个数
long count = animalStream.count();// 输出 5
System.out.println(count);

2. 收集

2.1 collect

collect 操作可以让你将 Stream 流中的所有元素收集到一个集合或者一个值中,返回一个收集结果。你需要指定一个收集器(Collector)来定义收集的规则。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 collect 操作将所有元素收集到一个列表中,使用预定义的收集器
List<String> list = animalStream.collect(Collectors.toList());// 输出 [cat, dog, elephant, fox, giraffe]
System.out.println(list);// 使用 collect 操作将所有元素收集到一个字符串中,使用自定义的收集器
String string = animalStream.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString();// 输出 catdogelephantfoxgiraffe
System.out.println(string);

2.2 toList

toList 操作可以让你将 Stream 流中的所有元素收集到一个列表中,返回一个列表。它是一个预定义的收集器,可以直接使用。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 toList 操作将所有元素收集到一个列表中
List<String> list = animalStream.toList();// 输出 [cat, dog, elephant, fox, giraffe]
System.out.println(list);

2.3 toSet

toSet 操作可以让你将 Stream 流中的所有元素收集到一个集合中,返回一个集合。它是一个预定义的收集器,可以直接使用。它会去除重复的元素。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "cat", "elephant", "dog", "fox");// 使用 toSet 操作将所有元素收集到一个集合中
Set<String> set = animalStream.toSet();// 输出 [cat, dog, elephant, fox]
System.out.println(set);

2.4 toMap

toMap 操作可以让你将 Stream 流中的所有元素收集到一个映射中,返回一个映射。它是一个预定义的收集器,可以直接使用。你需要指定一个键函数(Key Function)和一个值函数(Value Function)来定义映射的键和值。你也可以指定一个合并函数(Merge Function)来处理重复的键。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 toMap 操作将所有元素收集到一个映射中,以元素的首字母为键,以元素的长度为值
Map<String, Integer> map1 = animalStream.collect(Collectors.toMap(s -> s.substring(0, 1), String::length));// 输出 {c=3, d=3, e=8, f=3, g=7}
System.out.println(map1);// 使用 toMap 操作将所有元素收集到一个映射中,以元素的长度为键,以元素为值,如果有重复的键,就用逗号连接值
Map<Integer, String> map2 = animalStream.collect(Collectors.toMap(String::length, s -> s, (s1, s2) -> s1 + ", " + s2));// 输出 {3=cat, dog, fox, 8=elephant, 7=giraffe}
System.out.println(map2);

2.5 joining

joining 操作可以让你将 Stream 流中的所有元素连接成一个字符串,返回一个字符串。它是一个预定义的收集器,可以直接使用。你可以指定一个分隔符(Delimiter)来分隔元素,也可以指定一个前缀(Prefix)和一个后缀(Suffix)来包裹字符串。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 joining 操作将所有元素连接成一个字符串,不指定分隔符,前缀和后缀
String string1 = animalStream.collect(Collectors.joining());// 输出 catdogelephantfoxgiraffe
System.out.println(string1);// 使用 joining 操作将所有元素连接成一个字符串,指定分隔符为逗号,前缀为左括号,后缀为右括号
String string2 = animalStream.collect(Collectors.joining(", ", "(", ")"));// 输出 (cat, dog, elephant, fox, giraffe)
System.out.println(string2);

3. 遍历

3.1 forEach

forEach 操作可以让你对 Stream 流中的每个元素执行一个消费者(Consumer)操作,不返回任何结果。它是一个终端操作,会消耗 Stream 流。它不保证按照数据源的顺序执行,如果需要保证顺序,可以使用 forEachOrdered 操作。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 forEach 操作对每个元素打印一个消息
animalStream.forEach(s -> System.out.println("I like " + s));// 可能输出 I like fox, I like dog, I like cat, I like elephant, I like giraffe

3.2 forEachOrdered

forEachOrdered 操作可以让你对 Stream 流中的每个元素按照数据源的顺序执行一个消费者(Consumer)操作,不返回任何结果。它是一个终端操作,会消耗 Stream 流。它保证按照数据源的顺序执行,但可能会影响并行性能。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 forEachOrdered 操作对每个元素按照数据源的顺序打印一个消息
animalStream.forEachOrdered(s -> System.out.println("I like " + s));// 输出 I like cat, I like dog, I like elephant, I like fox, I like giraffe

4. 匹配

4.1 anyMatch

anyMatch 操作可以让你判断 Stream 流中是否有任意一个元素满足一个谓词(Predicate),返回一个布尔值。它是一个短路的终端操作,只要找到一个满足条件的元素就会停止。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 anyMatch 操作判断是否有以 f 开头的元素
boolean hasF = animalStream.anyMatch(s -> s.startsWith("f"));// 输出 true
System.out.println(hasF);

4.2 allMatch

allMatch 操作可以让你判断 Stream 流中是否所有的元素都满足一个谓词(Predicate),返回一个布尔值。它是一个短路的终端操作,只要找到一个不满足条件的元素就会停止。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 allMatch 操作判断是否所有的元素都包含 a
boolean allA = animalStream.allMatch(s -> s.contains("a"));// 输出 false
System.out.println(allA);

4.3 noneMatch

noneMatch 操作可以让你判断 Stream 流中是否没有任何一个元素满足一个谓词(Predicate),返回一个布尔值。它是一个短路的终端操作,只要找到一个满足条件的元素就会停止。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 noneMatch 操作判断是否没有以 z 结尾的元素
boolean noZ = animalStream.noneMatch(s -> s.endsWith("z"));// 输出 true
System.out.println(noZ);

5. 查找

5.1 findAny

findAny 操作可以让你从 Stream 流中找到任意一个元素,返回一个 Optional 对象,它可能包含一个值,也可能为空。它是一个短路的终端操作,只要找到一个元素就会停止。它不保证返回第一个元素,如果需要保证顺序,可以使用 findFirst 操作。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 findAny 操作找到任意一个元素
Optional<String> anyAnimal = animalStream.findAny();// 输出 Optional[cat] 或者其他值
System.out.println(anyAnimal);

5.2 findFirst

findFirst 操作可以让你从 Stream 流中找到第一个元素,返回一个 Optional 对象,它可能包含一个值,也可能为空。它是一个短路的终端操作,只要找到第一个元素就会停止。它保证返回第一个元素,但可能会影响并行性能。例如:

// 创建一个 Stream 流对象
Stream<String> animalStream = Stream.of("cat", "dog", "elephant", "fox", "giraffe");// 使用 findFirst 操作找到第一个元素
Optional<String> firstAnimal = animalStream.findFirst();// 输出 Optional[cat]
System.out.println(firstAnimal);

相关文章:

Java基础 - Stream 流:Stream API的终端操作

在前两篇博客中&#xff0c;我介绍了构建 Stream 流的多种方式&#xff0c;以及 Stream API 的中间操作&#xff0c;如果你还没有阅读&#xff0c;你可以点击这里和这里查看。 Java基础 - Stream 流&#xff1a;构建流的多种方式 Java基础 - Stream 流&#xff1a;Stream API…...

高级语言期末2009级A卷(计算机学院)

1.编写函数&#xff0c;打印下列序列0&#xff0c;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8&#xff0c;13&#xff0c;21&#xff0c;34...(斐波那契序列)的前n项 #include <stdio.h>int main() {int x0,y1,z,n;scanf("%d",&…...

docker-compose搭建php开发环境

Docker Compose简介 Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose&#xff0c;您可以使用 YML 文件来配置应用程序需要的所有服务。然后使用一个命令&#xff0c;就可以从 YML 文件配置中创建并启动所有服务。而DockerCompose作为一种容器编排工具&…...

翻译论文:Beating Floating Point at its Own Game: Posit Arithmetic(一)

仅作记录学习使用&#xff0c;侵删 原文Beating Floating Point at its Own Game: Posit Arithmetic 参考翻译Posit: 替换IEE754的新方式 | SIGARCH 摘要 IEEE标准754浮点数&#xff08;浮点数&#xff09;的直接接点替换 Posit的优势 不需要区间算术或可变大小操作数 如…...

【数据结构-图论】并查集

并查集&#xff08;Union-Find&#xff09;是一种数据结构&#xff0c;它提供了处理一些不交集的合并及查询问题的高效方法。并查集主要支持两种操作&#xff1a; 查找&#xff08;Find&#xff09;&#xff1a;确定某个元素属于哪个子集&#xff0c;这通常意味着找到该子集的…...

云计算时代的运维: 职业发展方向与岗位选择

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…...

java锁底层概述

Java中的锁是并发编程中核心的同步机制之一&#xff0c;用于控制多个线程对共享资源的访问&#xff0c;以保证数据的一致性和完整性。Java锁的底层实现依赖于操作系统的原生线程模型和Java虚拟机&#xff08;JVM&#xff09;的实现。这里主要讨论两种常见的锁&#xff1a;synch…...

win10如何添加指纹登陆

1、首先进入设置,进入下一个设置页面 2、在下一个设置页面内,我们直接使用右上角的搜索框,输入“指纹/finger”进行搜索。回车之后进入设置指纹登陆选项 3、设置指纹登陆的前期是设置好你的密码和pin码(先要设定登录密码和pin码),这里pin和密码都可以直接登陆我们的win10,设…...

足底筋膜炎的症状及治疗

足底筋膜炎症状&#xff1a;足底筋膜炎通常表现为足跟部疼痛&#xff0c;尤其是在晨起或长时间站立、行走后加重。疼痛可能向足底前部或足弓处放射&#xff0c;严重时可能影响行走。此外&#xff0c;患者还可能出现足跟部肿胀、皮肤温度升高、局部压痛等症状。 足底筋膜炎治疗方…...

udp丢包问题研究

//发现udp 有收不到数据包现象. 一: 观察丢包 1. ifconfig enp8s0 2. netstat -s -u 二: 修改系统缓存参数. recv_buffer_size 修改系统buffer_size sysctl -w net.core.rmem_max26214400 sysctl -w net.core.rmem_default26214400 三: 应用程序考虑 av_dict_set(&m_o…...

在idea中用模板骨架初始创建maven管理的web项目时没有src有关的目录的解决方案

一.问题如下 二.解决方法 首先关闭当前项目&#xff0c;接着修改全局设置&#xff0c;重新创建项目 在VM Options中添加"-DarchetypeCataloginternal"&#xff0c;点击ok保存 点击创建&#xff0c;如果创建成功没报错且有src&#xff0c;就ok了。 当然如果出现以下…...

WPF 【十月的寒流】学习笔记(2):MVVM中是怎么实现通知的

文章目录 前言相关链接代码仓库项目配置代码初始代码ViewPersonViewModel 尝试老办法通知解决方案ObservableCollectionBindingListICollectionView 总结 前言 我们这次详细了解一下列表通知的底层是怎么实现的 相关链接 十月的寒流 MVVM实战技巧之&#xff1a;可被观测的集合…...

数据结构:广义表

定义&#xff1a;有序数列  表示&#xff27;&#xff2c;&#xff1d;&#xff08;&#xff41;&#xff08;&#xff42;&#xff0c;&#xff43;&#xff09;&#xff09;长度 &#xff12;&#xff0c; 表头&#xff1a;&#xff41; 表尾&#xff1a;&#xff08;&am…...

你好,C++(18) 到底要不要买这个西瓜?4.1.6 操作符之间的优先顺序

你好&#xff0c;C&#xff08;18&#xff09; 到底要不要买这个西瓜&#xff1f;4.1.6 操作符之间的优先顺序 4.1.6 操作符之间的优先顺序 在表达一些比较复杂的条件判断时&#xff0c;在同一个表达式中&#xff0c;有时可能会存在多个操作符。比如&#xff0c;我们在判断要…...

C语言 for 循环语句的基本格式是什么?

一、问题 for 循环语句在C语⾔中是最为常见的循环语句&#xff0c;其功能强⼤&#xff0c;⽽且⽤法灵活&#xff0c;那么它的基本格式是什么呢&#xff1f; 二、解答 for 语句的⼀般形式为&#xff1a; for(表达式1;表达式2;表达3&#xff09;语句; 每条 for 语句包含三个⽤分…...

项目-SERVER模块-日志宏

日志宏 #define INF 0 #define DBG 1 #define ERR 2#define LOG_LEVEL INF #define LOG(level, format, ...) do {\if (level < LOG_LEVEL) break;\time_t t time(NULL);\struct tm *ltm localtime(&t);\char tmp[32] {0};\strftime(tmp, 31, "%H:%M:%S"…...

TCP为什么要三次握手?

TCP三次握手协议是为了在不可靠的互联网环境中可靠地建立起一个连接&#xff0c;三次握手可以确保两端的发送和接收能力都是正常的。 那么&#xff0c;为什么是三次而不是二次或四次握手呢&#xff1f; 为什么不是二次握手&#xff1f; 如果是二次握手&#xff0c;即客户端发…...

网络防御第6次作业

防病毒网关 按照传播方式分类 病毒 病毒是一种基于硬件和操作系统的程序&#xff0c;具有感染和破坏能力&#xff0c;这与病毒程序的结构有关。病毒攻击的宿主程序是病毒的栖身地&#xff0c;它是病毒传播的目的地&#xff0c;又是下一次感染的出发点。计算机病毒感染的一般过…...

Jmeter分布式部署

前期准备&#xff1a; 1. 控制机一台&#xff0c;代理机一台&#xff0c;Jmeter安装包 操作步骤&#xff1a; 1. Linux安装Jmeter&#xff08;windows安装教程自己搜一下&#xff09; 1.1创建一个单独的文件夹(jmeter)&#xff0c;用来存放Jmeter的安装包 mkdir jmeter 1.2…...

Odoo迈入开源第一低代码开发平台的重要里程碑

Odoo17的正式发布已经过去好几个月了&#xff0c;通过一段时间的运用&#xff0c;最大的感触就是&#xff0c;Odoo会成为企业管理软件低代码开发平台的重要一员&#xff0c;而V17则会成为这个过程中具有里程碑意义的版本。 时隔四个月&#xff0c;让我们回头来看看Odoo17带来的…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...