Java Stream API详解:高效处理集合数据的利器
引言
Java 8引入了许多新特性,其中最为显著的莫过于Lambda表达式和Stream API。Stream API提供了一种高效、简洁的方法来处理集合数据,使代码更加简洁明了,且具有较高的可读性和可维护性。本文将深入探讨Java Stream API的使用,包括基础概念、常用操作、并行处理、实战案例以及最佳实践等内容。
目录
- 什么是Stream API
- Stream API的基础操作
- 创建Stream
- 中间操作
- 终端操作
- Stream API的高级操作
- 排序
- 筛选
- 映射
- 规约
- 收集
- 并行Stream
- Stream API实战案例
- 处理集合数据
- 文件操作
- 数据库操作
- Stream API的最佳实践
- 常见问题与解决方案
- 总结
什么是Stream API
Stream API是Java 8引入的一种用于处理集合数据的抽象,它允许以声明性方式(类似SQL语句)来处理数据。Stream API提供了许多强大的操作,可以用来对集合进行过滤、排序、映射、规约等操作,极大地简化了代码。
特点
- 声明性编程:使用Stream API可以以声明性的方式编写代码,减少样板代码。
- 链式调用:Stream API的操作可以链式调用,提高代码的可读性。
- 惰性求值:中间操作是惰性求值的,只有在执行终端操作时才会进行计算。
- 并行处理:支持并行处理,可以充分利用多核CPU的优势。
Stream API的基础操作
创建Stream
Stream API提供了多种方式来创建Stream,常见的有以下几种:
- 从集合创建:
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
- 从数组创建:
String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
- 使用
Stream.of:
Stream<String> stream = Stream.of("a", "b", "c");
- 使用
Stream.generate:
Stream<Double> stream = Stream.generate(Math::random).limit(10);
- 使用
Stream.iterate:
Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(10);
中间操作
中间操作用于转换Stream,是惰性求值的,常见的中间操作有以下几种:
filter:用于过滤元素。
Stream<String> stream = list.stream().filter(s -> s.startsWith("a"));
map:用于映射每个元素到对应的结果。
Stream<String> stream = list.stream().map(String::toUpperCase);
flatMap:用于将每个元素转换为Stream,然后合并成一个Stream。
Stream<String> stream = list.stream().flatMap(s -> Stream.of(s.split("")));
distinct:用于去重。
Stream<String> stream = list.stream().distinct();
sorted:用于排序。
Stream<String> stream = list.stream().sorted();
peek:用于在处理过程中查看每个元素。
Stream<String> stream = list.stream().peek(System.out::println);
终端操作
终端操作用于启动Stream的计算,并生成结果,常见的终端操作有以下几种:
forEach:对每个元素执行操作。
list.stream().forEach(System.out::println);
collect:将Stream转换为其他形式。
List<String> result = list.stream().collect(Collectors.toList());
reduce:将Stream中的元素规约成一个值。
Optional<String> result = list.stream().reduce((s1, s2) -> s1 + s2);
toArray:将Stream转换为数组。
String[] array = list.stream().toArray(String[]::new);
count:计算元素个数。
long count = list.stream().count();
anyMatch、allMatch、noneMatch:用于匹配判断。
boolean anyMatch = list.stream().anyMatch(s -> s.startsWith("a"));
boolean allMatch = list.stream().allMatch(s -> s.startsWith("a"));
boolean noneMatch = list.stream().noneMatch(s -> s.startsWith("a"));
findFirst、findAny:用于查找元素。
Optional<String> first = list.stream().findFirst();
Optional<String> any = list.stream().findAny();
Stream API的高级操作
排序
使用sorted方法对Stream进行排序,可以传入一个比较器。
List<String> list = Arrays.asList("b", "c", "a");
List<String> sortedList = list.stream().sorted().collect(Collectors.toList());
// 逆序排序
List<String> sortedListDesc = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
筛选
使用filter方法对Stream中的元素进行筛选。
List<String> list = Arrays.asList("a", "b", "c");
List<String> filteredList = list.stream().filter(s -> s.startsWith("a")).collect(Collectors.toList());
映射
使用map方法对Stream中的元素进行映射。
List<String> list = Arrays.asList("a", "b", "c");
List<String> mappedList = list.stream().map(String::toUpperCase).collect(Collectors.toList());
规约
使用reduce方法对Stream中的元素进行规约。
List<String> list = Arrays.asList("a", "b", "c");
String result = list.stream().reduce("", (s1, s2) -> s1 + s2);
收集
使用collect方法将Stream转换为其他形式。
List<String> list = Arrays.asList("a", "b", "c");
List<String> collectedList = list.stream().collect(Collectors.toList());
Set<String> collectedSet = list.stream().collect(Collectors.toSet());
String joinedString = list.stream().collect(Collectors.joining(","));
并行Stream
并行Stream可以充分利用多核CPU的优势,提高数据处理的效率。可以使用parallelStream方法创建并行Stream。
List<String> list = Arrays.asList("a", "b", "c");
List<String> parallelList = list.parallelStream().map(String::toUpperCase).collect(Collectors.toList());
也可以使用parallel方法将普通Stream转换为并行Stream。
List<String> list = Arrays.asList("a", "b", "c");
List<String> parallelList = list.stream().parallel().map(String::toUpperCase).collect(Collectors.toList());
需要注意的是,并行Stream并不是总是比串行Stream更快,具体需要根据具体情况进行测试。
Stream API实战案例
处理集合数据
案例一:过滤并转换集合
给定一个包含若干字符串的集合,过滤掉长度小于3的字符串,并将剩余字符串转换为大写。
List<String> list = Arrays.asList("a", "ab", "abc", "abcd");
List<String> result = list.stream().filter(s -> s.length() >= 3).map(String::toUpperCase).collect(Collectors.toList());
System.out.println(result); // 输出:[ABC, ABCD]
案例二:计算平均值
给定一个包含若干整数的集合,计算所有整数的平均值。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
OptionalDouble average = list.stream().mapToInt(Integer::intValue).average();
average.ifPresent(System.out::println); // 输出:3.0
文件操作
案例三:读取文件内容
使用Stream API
读取文件内容并输出到控制台。
try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {lines.forEach(System.out::println);
} catch (IOException e) {e.printStackTrace();
}
案例四:统计单词出现次数
读取文件内容并统计每个单词出现的次数。
try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {Map<String, Long> wordCount = lines.flatMap(line -> Arrays.stream(line.split("\\W+"))).collect(Collectors.groupingBy(String::toLowerCase, Collectors.counting()));wordCount.forEach((word, count) -> System.out.println(word + ": " + count));
} catch (IOException e) {e.printStackTrace();
}
数据库操作
案例五:处理数据库查询结果
假设我们有一个数据库表users,包含字段id、name和age。我们可以使用Stream API处理查询结果。
List<User> users = queryDatabase();
List<String> names = users.stream().filter(user -> user.getAge() > 18).map(User::getName).collect(Collectors.toList());
System.out.println(names);
Stream API的最佳实践
- 避免不必要的并行化:并行Stream并不是总是更快,应该根据具体情况进行选择。
- 合理使用中间操作和终端操作:中间操作是惰性求值的,只有在执行终端操作时才会进行计算。
- 注意Stream的可复用性:Stream一旦被消费就不能再使用,如果需要复用,可以考虑将Stream转换为集合再使用。
- 使用合适的收集器:
Collectors类提供了多种收集器,可以根据具体需求选择合适的收集器。 - 处理异常:在使用Stream API时,需要处理可能出现的异常,尤其是在文件操作和数据库操作中。
常见问题与解决方案
Stream已关闭
Stream一旦被消费就不能再使用,如果需要复用,可以考虑将Stream转换为集合再使用。
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println); // 会抛出IllegalStateException
性能问题
并行Stream并不是总是比串行Stream更快,具体需要根据具体情况进行测试。可以使用ForkJoinPool来优化并行Stream的性能。
ForkJoinPool customThreadPool = new ForkJoinPool(4);
customThreadPool.submit(() ->list.parallelStream().forEach(System.out::println)
).get();
内存泄漏
在使用Stream API处理大数据量时,需要注意内存泄漏的问题。可以使用close方法关闭Stream,或者使用try-with-resources语句自动关闭Stream。
try (Stream<String> lines = Files.lines(Paths.get("example.txt"))) {lines.forEach(System.out::println);
} catch (IOException e) {e.printStackTrace();
}
总结
本文详细介绍了Java Stream API的使用,包括基础操作、高级操作、并行处理、实战案例以及最佳实践等内容。通过合理利用Stream API,开发者可以大大简化代码,提高代码的可读性和可维护性,同时还可以提高数据处理的效率。希望本文对你在Java开发中的Stream API使用有所帮助。
Java Stream API是处理集合数据的强大工具,通过灵活运用各种操作,可以实现高效的数据处理和流式计算。如果你还没有使用过Stream API,建议尽快学习和掌握这一强大的工具,将其应用到你的项目中,提升开发效率和代码质量。
相关文章:
Java Stream API详解:高效处理集合数据的利器
引言 Java 8引入了许多新特性,其中最为显著的莫过于Lambda表达式和Stream API。Stream API提供了一种高效、简洁的方法来处理集合数据,使代码更加简洁明了,且具有较高的可读性和可维护性。本文将深入探讨Java Stream API的使用,包…...
Python使用策略模式和openpyxl库创建Excel文件并追加内容
from openpyxl import load_workbook# 数据数组 data [[1, 2, 3],[4, 5, 6],[7, 8, 9] ]# 打开现有的 Excel 文件 excel_file sheetApend_example.xlsx wb load_workbook(excel_file)# 选择要追加数据的工作表 sheet_name test_Sheet2 # 指定要追加数据的工作表名称 sheet…...
libcoap3对接华为云平台
文章目录 前言一、平台注册二、引入源码库1.libcoap仓库编译2.分析网络报文3.案例代码4.编译&运行 总结 前言 通过libcoap3开源代码库对接华为云平台,本文章将讨论加密与不加密的方式对接华为云平台。 一、平台注册 首先,你需要在华为云平台上创建…...
【鸿蒙学习笔记】关系型数据库概述
目录标题 关系型数据库的运行机制样例代码共通方法 DBUtilsIndex 代码效果 关系型数据库的运行机制 1、 关系型数据库对应用提供通用的操作接口,底层使用SQLite作为持久化存储引擎,支持SQLite具有的数据库特性,包括但不限于事务、索引、视图…...
Find My网球拍|苹果Find My技术与网球拍结合,智能防丢,全球定位
网球是球类运动项目之一,网球拍作为这项运动的必备工具,有木质球拍、铝合金球拍、钢质球拍和复合物(尼龙、碳素)球拍,任何材质的球拍均可用于比赛。网球拍由拍头、拍喉、拍柄组成,在使用时还需要配合网球线…...
windows环境下部署多个端口Tomcat服务和开机自启动设置保姆级教程
前言 本文主要介绍了 windows环境下,配置多个Tomcat设置不同端口启动服务。其实在思路上Linux上也是适用的,只是 Linux 上没有可视化客户端,会麻烦些,但总体的思路上是一样的。 注:文章中涉及些文字和图片是搬运了其他…...
科普文:一文搞懂jvm实战(四)深入理解逃逸分析Escape Analysis
概叙 Java 中的对象是否都分配在堆内存中? 好了太抽象了,那具体一点,看看下面这个对象是在哪里分配内存? public void test() { Object object new Object(); }这个方法中的object对象,是在堆中分配内存么࿱…...
中文大模型发展到哪一个阶段了?
中文大模型发展到哪一个阶段了? 近日,中文大模型综合性测评基准SuperCLUE,发布了上半年大模型中文综合评测报告。“百模大战”中,OpenAI的GPT-4o是表现最优秀的大模型,但国内大模型已将差缩小至4.8%。国内大模型崛起迅…...
【PostgreSQL】Spring boot + Mybatis-plus + PostgreSQL 处理json类型情况
Spring boot Mybatis-plus PostgreSQL 处理json类型情况 一、前言二、技术栈三、背景分析四、方案分析4.1 在PostgreSQL 数据库中直接存储 json 对象4.2 在PostgreSQL 数据库中存储 json 字符串 五、自定义类型处理器5.1 定义类型处理器5.2 使用自定义类型处理器 一、前言 在…...
华为910b推理Qwen1.5-72b
前情提要:华为910b部署训练推理大模型,本人之前并没有接触过,所以,写此文档进行记录。 (注意:版本适配很重要!!不然就像我一样走了好多坑~~~) 首先,看一张图…...
legoloam算法环境配置和调试笔记
安装gtsam 参考 Ubuntu20.04安装gtsam记录_gtsam安装-CSDN博客 mkdir buildcd buildcmake .. make -...
如何用CSS3画一个三角形?
要用 CSS3 画一个三角形,可以利用元素的边框和透明边框的特性来实现。以下是一个简单的示例代码: .triangle {width: 0;height: 0;border-left: 50px solid transparent; /* 左边框为透明,控制三角形的左斜边 */border-right: 50px solid tr…...
不同型号的GD32 MCU如何区分?
大家是否碰到过以下应用场景:同一套软件代码希望跑在不同型号的GD32 MCU中,但有些地方需要根据MCU型号进行调整?或者上位机或其他MCU与GD32 MCU通信时需要知道对应的MCU型号是哪个? 此时,我们就需要了解如何获取以及区…...
关于windows下编译xLua插件的流程记录
1.工程准备 1.xLua工程:GitHub - Tencent/xLua: xLua is a lua programming solution for C# ( Unity, .Net, Mono) , it supports android, ios, windows, linux, osx, etc. 2.build_xlua_with_libs工程:GitHub - chexiongsheng/build_xlua_with_libs…...
Hadoop简明教程
文章目录 关于HadoopHadoop拓扑结构Namenode 和 Datanode 基本管理启动Hadoop启动YARN验证Hadoop服务停止Hadoop停止HDFS Hadoop集群搭建步骤准备阶段Java环境配置Hadoop安装与配置HDFS格式化与启动服务测试集群安装额外组件监控与维护: 使用Docker搭建集群使用Hado…...
基于STM32设计的药品柜温湿度监测系统(华为云IOT)(184)
基于STM32设计的药品柜温湿度监测系统(华为云IOT)(184) 文章目录 一、前言1.1 项目介绍【1】项目功能介绍【2】整体需求总结【3】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】ESP8266工作模式配置【3】华为云IOT手机APP界面开发思路1.3 项目开发背景【1】选题的意义【2…...
SpringBoot源码阅读(10)——后处理器
后处理器是在监听器EnvironmentPostProcessorApplicationListener中被加载。 入口在SpringApplication实例方法prepareEnvironment,第343行。 listeners.environmentPrepared(bootstrapContext, environment);这里触发了事件ApplicationEnvironmentPreparedEvent 相…...
【源码开源】C#桌面应用开发:串口调试助手
c#桌面应用开发 1、环境搭建和工程创建:参照番茄定时器项目 工程创建参照 2、界面布局设计 3、具体功能函数 (1)端口扫描: private void btn_com_scan_Click(object sender, EventArgs e){//端口号扫描ReflashPortToComboBox(…...
malloc与free函数的用法(精简全面 · 一看即懂)
前言:Hello大家好😘,我是心跳sy,今天为大家带来malloc函数与free函数的用法,我们一起来看看吧! 目录 一、malloc函数 💫 1、⭐️malloc函数对应的头文件⭐️ 2、⭐️malloc函数的作用⭐️ 3…...
强制升级最新系统,微软全面淘汰Win10和部分11用户
说出来可能不信,距离 Windows 11 正式发布已过去整整三年时间,按理说现在怎么也得人均 Win 11 水平了吧? 然而事实却是,三年时间过去 Win 11 占有率仅仅突破到 29%,也就跳起来摸 Win 10 屁股的程度。 2024 年 6 月 Wi…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
