Java进阶-Java Stream API详解与使用

news2024/11/23 4:27:08

本文全面介绍了 Java Stream API 的概念、功能以及如何在 Java 中有效地使用它进行集合和数据流的处理。通过详细解释和示例,文章展示了 Java Stream API 在简化代码、提高效率以及支持函数式编程方面的优势。文中还比较了 Java Stream API 与其他集合处理库的异同,强调了其在现代 Java 开发中的重要性和实用性。
在这里插入图片描述


一、Java Stream API介绍

1. Java Stream API简述

Java Stream API 是Java 8中引入的一项功能,它允许程序员以声明式方式处理数据集合。通过Stream API,可以对数据执行复杂的查询操作,而不必编写冗余的代码。Stream 不是数据结构,它更像是一个高级版本的Iterator。单次使用,数据只能遍历一次,遍历过程中你可以对数据进行过滤、排序、聚合等操作。


2. Java Stream API支持的功能

功能描述
filter过滤流中的元素,根据条件只留下满足条件的元素
map将流中的每个元素映射成其他形式,结果是一个包含映射后结果的新流
sorted确保流中的元素在消费时的顺序按照自然顺序或自定义Comparator排序
collect将流转换为其他形式,如List、Set或Map,或者是自定义的收集器
forEach遍历流中的每个元素并执行给定的操作
reduce通过重复处理其元素来将流减少到单个汇总结果
anyMatch检查流中的元素是否有一个满足给定的条件
allMatch检查流中的元素是否全部满足给定条件
noneMatch检查流中的元素是否没有满足给定条件的
findFirst返回流中的第一个元素,如果流为空,则返回空的Optional
limit截断流,使其最大长度不超过给定数量
skip跳过流中的前n个元素,返回包含余下元素的新流

3. 使用Java Stream API的优势

功能Java Stream API传统集合操作
数据处理模式声明式,支持函数式编程命令式,代码较为复杂
内存效率更高,因为它是在流上直接操作低,需要复制到新的数据结构
并发处理内建支持并发处理手动处理并发
可读性高,流操作可链式调用低,循环和条件判断多
使用场景数据集合操作,大数据处理小数据量操作

二、常用的Java Stream API功能

下面是针对每个Java Stream API函数的示例代码:

1. filter

过滤流中的元素,根据条件只留下满足条件的元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream()
                                   .filter(n -> n % 2 == 0)
                                   .collect(Collectors.toList());
System.out.println(evenNumbers); // 输出 [2, 4, 6]

2. map

将流中的每个元素映射成其他形式,结果是一个包含映射后结果的新流。

List<String> words = Arrays.asList("hello", "world", "java", "stream");
List<Integer> wordLengths = words.stream()
                                 .map(String::length)
                                 .collect(Collectors.toList());
System.out.println(wordLengths); // 输出 [5, 5, 4, 6]

3. sorted

确保流中的元素在消费时的顺序按照自然顺序或自定义Comparator排序。

List<Integer> numbers = Arrays.asList(4, 3, 6, 1, 5, 2);
List<Integer> sortedNumbers = numbers.stream()
                                     .sorted()
                                     .collect(Collectors.toList());
System.out.println(sortedNumbers); // 输出 [1, 2, 3, 4, 5, 6]

4. collect

将流转换为其他形式,如List、Set或Map,或者是自定义的收集器。

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
Set<String> nameSet = names.stream()
                           .collect(Collectors.toSet());
System.out.println(nameSet); // 输出 [Alice, Bob, Charlie, David]

5. forEach

遍历流中的每个元素并执行给定的操作。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
names.stream()
     .forEach(System.out::println); // 依次输出 1、2、3、4、5

6. reduce

通过重复处理其元素来将流减少到单个汇总结果。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
                 .reduce(0, Integer::sum);
System.out.println("Sum: " + sum); // 输出 Sum: 15

7. anyMatch

检查流中的元素是否有一个满足给定的条件。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean hasEven = numbers.stream()
                         .anyMatch(n -> n % 2 == 0);
System.out.println("Has even numbers: " + hasEven); // 输出 Has even numbers: true

8. allMatch

检查流中的元素是否全部满足给定条件。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allEven = numbers.stream()
                         .allMatch(n -> n % 2 == 0);
System.out.println("All are even: " + allEven); // 输出 All are even: false

9. noneMatch

检查流中的元素是否没有满足给定条件的。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean noneMultipleOfTen = numbers.stream()
                                   .noneMatch(n -> n % 10 == 0);
System.out.println("None are multiples of ten: " + noneMultipleOfTen); // 输出 None are multiples of ten: true

10. findFirst

返回流中的第一个元素,如果流为空,则返回空的Optional。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> first = numbers.stream()
                                 .findFirst();
System.out.println("First number: " + first.orElse(-1)); // 输出 First number: 1

11. limit

截断流,使其最大长度不超过给定数量。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limited = numbers.stream()
                               .limit(3)
                               .collect(Collectors.toList());
System.out.println(limited); // 输出 [1, 2, 3]

12. skip

跳过流中的前n个元素,返回包含余下元素的新流。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skipped = numbers.stream()
                               .skip(3)
                               .collect(Collectors.toList());
System.out.println(skipped); // 输出 [4, 5]

这些示例展示了Java Stream API的多样化和强大功能,使得处理集合数据更加灵活和


三、Java Stream API和类似包比较的优势

Java Stream API 作为Java 8及以后版本的核心特性,对集合和数据流的处理提供了强大的支持。除了Java自带的Stream API,还有一些其他的库或框架也提供了类似的功能,用于处理集合或者数据流。

1. 常见的Java集合处理库

  1. Java Stream API - 内置于Java 8及以上版本,提供了一种高级的处理集合的方法,支持函数式编程。
  2. Apache Commons Collections - 提供了丰富的集合操作工具,但主要是针对Java集合框架之前的版本设计。
  3. Google Guava - 提供了许多核心Java库没有的集合类型和工具,包括对集合的操作和新的集合类型。
  4. Vavr(之前称为Javaslang)- 提供了不可变的集合类型和其他函数式编程的工具,以提高代码的健壮性。
  5. Eclipse Collections(之前称为GS Collections)- 提供了一套丰富的集合库,以及各种性能优化和内存优化的集合类型。

2. 集合处理库之间的比较

特性 / 库Java Stream APIApache Commons CollectionsGoogle GuavaVavrEclipse Collections
主要优势内置支持,无需额外依赖丰富的集合操作工具强大的集合工具和新集合类型不可变集合和函数式编程支持高性能、丰富的集合类型
集合不可变性不提供不提供提供部分不可变集合所有集合默认不可变提供不可变和可变集合
函数式编程支持有限支持有限支持完全支持有限支持
并发支持并发流处理不专门针对并发优化提供并发集合不提供提供优化的并发集合
类型安全和检查类型安全类型安全类型安全类型安全类型安全
学习曲线中等中等中等
与Java版本兼容性Java 8+Java 1.2+Java 1.6+Java 8+Java 5+
扩展集合类型提供额外集合操作提供新的集合类型提供函数式集合类型提供丰富的集合类型

每个库都有其独特的优点和用途。Java Stream API是Java开发中的标准选项,无需额外依赖且与现代Java应用高度兼容。对于需要在老版本Java上工作的开发者,Apache Commons Collections提供了后向兼容。Google Guava和Eclipse Collections提供了高性能的集合操作,而Vavr则为喜欢函数式编程的开发者提供了很好的支持。选择哪个库取决于具体的项目需求、团队的熟悉度以及对库特性的需求。


四、Java Stream API使用总结

Java Stream API 是一个功能强大的工具,适用于处理集合和数据流。它提供了一种简洁而高效的方法来操作数据,尤其是在处理大量数据时。这个API优化了数据处理逻辑,使开发者能够以更少的代码执行复杂的数据转换和聚合操作。利用Java Stream API,可以轻松实现数据过滤、排序、转换及汇总,极大地提升了代码的可读性和可维护性。同时,Stream API 的函数式编程特性有助于减少错误和侧效应,使得并发程序的编写更为安全。通过使用Java Stream API,开发者可以写出更简洁、更高效、更易于维护的代码,同时享受到函数式编程带来的好处。

在这里插入图片描述

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

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

相关文章

分类预测 | MATLAB实现LSSVM最小二乘支持向量机多分类预测

分类预测 | MATLAB实现LSSVM最小二乘支持向量机多分类预测 目录 分类预测 | MATLAB实现LSSVM最小二乘支持向量机多分类预测分类效果基本介绍程序设计参考资料分类效果 基本介绍 MATLAB实现LSSVM最小二乘支持向量机多分类预测。最小二乘支持向量机(Least Squares Support Vecto…

数据结构学习/复习1--时间复杂度计算/异或的几个实际用途

一、什么是数据结构和算法 1注&#xff1a;在内存中的存储管理数据 2注&#xff1a;解决问题的方法 二、时间复杂度 1.算法的效率 2.时间复杂度的概念 计算时间复杂度案例1&#xff1a; 计算时间复杂度案例2&#xff1a; 计算时间复杂度案例3&#xff1a; 计算…

如何将本地Android studio项目上传到GitHub

操作步骤&#xff1a; 1、在GitHub上创建账户 2、在androd studio中添加上述创建的GitHub账号 3、在android studio上找到"share project on GitHub"&#xff0c;点击此选项上传当前项目到GitHub 上传成功后&#xff0c;会在GitHub上创建默认仓库repository 注&a…

【R语言数据分析】基本运算与数据导入速查

R语言中命名可以包含英文字母&#xff0c;下划线&#xff0c;数字&#xff0c;点&#xff0c;下划线和数字不能作为名字的开头&#xff0c;点可以开头&#xff0c;但是点开头后面不能跟数字。一般的命名就是只使用英文和下划线就够了。 四则运算 R语言的除法是即使给的两个数…

常用算法代码模板 (2) :数据结构

AcWing算法基础课笔记与常用算法模板 (2) ——数据结构 常用算法代码模板 (1) &#xff1a;基础算法 常用算法代码模板 (2) &#xff1a;数据结构 常用算法代码模板 (3) &#xff1a;搜索与图论 常用算法代码模板 (4) &#xff1a;数学知识 算法基础课 动态规划模板题笔记 算法…

857.雇佣K名工人的最低成本

题目说的其实是有点乱的,所以我们可能抓不住重点,甚至都不太清楚规则,比如 eg. quality[3,1,10,10,1] wage[4,8,200,200,7] 这里是选下标0,1,4 ->单价为8 但是想清楚其实就很easy. 就是 贪心(sort) 优先队列 梳理下我们发现其实要让每个人得到最低期望,就要按照当前最贵…

项目管理-高级项目管理

1.高级项目管理--主要内容 高级项目管理&#xff0c;以下主要从5方面介绍&#xff1a;项目集管理、项目组合管理、组织级项目管理OPM、量化组织管理、项目管理实践模型。 2.具体内容 2.1项目集管理 项目管理绩效域&#xff1a; 包括项目集战略一致性、项目集效益管理、项目集干…

ip地址与硬件地址的区别是什么

在数字世界的浩瀚海洋中&#xff0c;每一台联网的设备都需要一个独特的标识来确保信息的准确传输。这些标识&#xff0c;我们通常称之为IP地址和硬件地址。虽然它们都是用来识别网络设备的&#xff0c;但各自扮演的角色和所处的层次却大相径庭。虎观代理小二将带您深入了解IP地…

【记录】Springboot项目集成docker实现一键部署

公司管理平台完成后&#xff0c;为了方便其他不懂开发的同事部署和测试&#xff0c;集成docker进行一键部署&#xff0c;也为后面自动化部署做准备。本文做个简单记录。 1、安装docker yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/cont…

剃齿和磨齿工艺比较

众所周知&#xff0c;剃齿加工和磨削加工是两种不同的齿轮精加工方法。剃齿是在热处理前进行的&#xff08;这也是剃齿加工受限的原因&#xff09;&#xff0c;而磨齿是在热处理之后进行的。近几年来&#xff0c;随着机械加工精度的不断提高、数控机床的不断完善以及加工软件的…

软件项目总体测试方案

测试目标&#xff1a;确保项目的需求分析说明书中的所有功能需求都已实现&#xff0c;且能正常运行&#xff1b;确保项目的业务流程符合用户和产品设计要求&#xff1b;确保项目的界面美观、风格一致、易学习、易操作、易理解。 软件全套文档过去进主页。 一、 前言 &#x…

AngularJS 的生命周期和基础语法

AngularJS 的生命周期和基础语法 文章目录 AngularJS 的生命周期和基础语法1. 使用步骤2. 生命周期钩子函数3. 点击事件4. if 语句1. if 形式2. if else 形式 5. for 语句6. switch 语句7. 双向数据绑定 1. 使用步骤 // 1. 要使用哪个钩子函数&#xff0c;就先引入 import { O…

【跟我学RISC-V】(一)认识RISC-V指令集并搭建实验环境

写在前面 现在计算机的体系架构正是发展得如火如荼的时候&#xff0c;占领桌面端市场的x86架构、占领移动端市场的arm架构、在服务器市场仍有一定地位的mips架构、国产自研的指令集loongarch架构、还有我现在要讲到的新型开源开放的RISC-V指令集架构。 我先说一说我的学习经历…

区块链 | IPFS 工作原理入门

&#x1f98a;原文&#xff1a;What is the InterPlanetary File System (IPFS), and how does it work? &#x1f98a;写在前面&#xff1a;本文属于搬运博客&#xff0c;自己留存学习。 1 去中心化互联网 尽管万维网是一个全球性的网络&#xff0c;但在数据存储方面&#…

LeetCode热题100:双指针

283.移动零 题目链接&#xff1a;移动零 题目描述&#xff1a;给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 解题思路&#xff1a; 创建两…

三种滤波(EKF、UKF、CKF)的对比,含MATLAB源代码

使用MATLAB模拟三维的滤波,包含扩展卡尔曼滤波EKF、无迹卡尔曼滤波UKF、容积卡尔曼滤波CKF。 状态更新和观测更新均为非线性的,模拟一定强度的机动性,可用于卡尔曼滤波方法的对比学习,自己修改成需要的运动模型后,可以用于组合导航(GPS+DVL形式)。 运行结果 真值的三轴…

c#word文档:3.向Word文档中插入表格/4.读取Word文档中表格

--向Word文档中插入表格-- &#xff08;1&#xff09;在OfficeOperator项目的WordOperator类中定义向Word文档插入换页的函数NewPage &#xff08;2&#xff09;在WordOperator类中定义向Word文档插入表格的函数InsertTable using Microsoft.Office.Interop.Word;// 引入Mic…

不小心格式化固态硬盘之后,数据能恢复吗?小白实测

前言 这段时间突然想到一件事情&#xff1a;固态硬盘一旦坏了&#xff0c;数据恢复的可能性基本上是0。 这件事情是小白自己亲身经历的&#xff0c;所以使用固态硬盘的小伙伴一定要注意数据备份&#xff0c;至少备一份到机械硬盘里&#xff0c;还会稍微可靠一些。 这几天小白…

node.js的常用内置库(1)共128节

我说假如node.js 一路杀出&#xff0c;成为一种后端主要选型的时候&#xff0c;你再次去了解晚么&#xff0c;不晚&#xff0c;但给你的时间肯定不多&#xff5e;&#x1f604; 跟着我一起开始认识node吧&#xff0c;今日份不多3个API &#xff0c;加油 1.assert 在 Node.js 环…

水稻病害检测(YOLO数据集,多分类,稻瘟病、纹枯病、褐斑病、枯心病、霜霉病、水稻细菌性条纹斑病、稻苞虫)

是自己利用LabelImg工具进行手工标注&#xff0c;数据集制作不易&#xff0c;请尊重版权&#xff08;稻瘟病、纹枯病、褐斑病、枯心病、霜霉病、水稻细菌性条纹斑病、稻苞虫&#xff09; 如果需要yolv8检测模型和数据集放在一起的压缩包&#xff0c;可以关注&#xff1a;最新最…