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

Java Stream API详解:高效处理集合数据的利器

引言

Java 8引入了许多新特性,其中最为显著的莫过于Lambda表达式和Stream API。Stream API提供了一种高效、简洁的方法来处理集合数据,使代码更加简洁明了,且具有较高的可读性和可维护性。本文将深入探讨Java Stream API的使用,包括基础概念、常用操作、并行处理、实战案例以及最佳实践等内容。

目录

  1. 什么是Stream API
  2. Stream API的基础操作
    • 创建Stream
    • 中间操作
    • 终端操作
  3. Stream API的高级操作
    • 排序
    • 筛选
    • 映射
    • 规约
    • 收集
  4. 并行Stream
  5. Stream API实战案例
    • 处理集合数据
    • 文件操作
    • 数据库操作
  6. Stream API的最佳实践
  7. 常见问题与解决方案
  8. 总结

什么是Stream API

Stream API是Java 8引入的一种用于处理集合数据的抽象,它允许以声明性方式(类似SQL语句)来处理数据。Stream API提供了许多强大的操作,可以用来对集合进行过滤、排序、映射、规约等操作,极大地简化了代码。

特点

  • 声明性编程:使用Stream API可以以声明性的方式编写代码,减少样板代码。
  • 链式调用:Stream API的操作可以链式调用,提高代码的可读性。
  • 惰性求值:中间操作是惰性求值的,只有在执行终端操作时才会进行计算。
  • 并行处理:支持并行处理,可以充分利用多核CPU的优势。

Stream API的基础操作

创建Stream

Stream API提供了多种方式来创建Stream,常见的有以下几种:

  1. 从集合创建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
  1. 从数组创建
String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
  1. 使用Stream.of
Stream<String> stream = Stream.of("a", "b", "c");
  1. 使用Stream.generate
Stream<Double> stream = Stream.generate(Math::random).limit(10);
  1. 使用Stream.iterate
Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(10);

中间操作

中间操作用于转换Stream,是惰性求值的,常见的中间操作有以下几种:

  1. filter:用于过滤元素。
Stream<String> stream = list.stream().filter(s -> s.startsWith("a"));
  1. map:用于映射每个元素到对应的结果。
Stream<String> stream = list.stream().map(String::toUpperCase);
  1. flatMap:用于将每个元素转换为Stream,然后合并成一个Stream。
Stream<String> stream = list.stream().flatMap(s -> Stream.of(s.split("")));
  1. distinct:用于去重。
Stream<String> stream = list.stream().distinct();
  1. sorted:用于排序。
Stream<String> stream = list.stream().sorted();
  1. peek:用于在处理过程中查看每个元素。
Stream<String> stream = list.stream().peek(System.out::println);

终端操作

终端操作用于启动Stream的计算,并生成结果,常见的终端操作有以下几种:

  1. forEach:对每个元素执行操作。
list.stream().forEach(System.out::println);
  1. collect:将Stream转换为其他形式。
List<String> result = list.stream().collect(Collectors.toList());
  1. reduce:将Stream中的元素规约成一个值。
Optional<String> result = list.stream().reduce((s1, s2) -> s1 + s2);
  1. toArray:将Stream转换为数组。
String[] array = list.stream().toArray(String[]::new);
  1. count:计算元素个数。
long count = list.stream().count();
  1. anyMatchallMatchnoneMatch:用于匹配判断。
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"));
  1. findFirstfindAny:用于查找元素。
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,包含字段idnameage。我们可以使用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的最佳实践

  1. 避免不必要的并行化:并行Stream并不是总是更快,应该根据具体情况进行选择。
  2. 合理使用中间操作和终端操作:中间操作是惰性求值的,只有在执行终端操作时才会进行计算。
  3. 注意Stream的可复用性:Stream一旦被消费就不能再使用,如果需要复用,可以考虑将Stream转换为集合再使用。
  4. 使用合适的收集器Collectors类提供了多种收集器,可以根据具体需求选择合适的收集器。
  5. 处理异常:在使用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引入了许多新特性&#xff0c;其中最为显著的莫过于Lambda表达式和Stream API。Stream API提供了一种高效、简洁的方法来处理集合数据&#xff0c;使代码更加简洁明了&#xff0c;且具有较高的可读性和可维护性。本文将深入探讨Java Stream API的使用&#xff0c;包…...

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开源代码库对接华为云平台&#xff0c;本文章将讨论加密与不加密的方式对接华为云平台。 一、平台注册 首先&#xff0c;你需要在华为云平台上创建…...

【鸿蒙学习笔记】关系型数据库概述

目录标题 关系型数据库的运行机制样例代码共通方法 DBUtilsIndex 代码效果 关系型数据库的运行机制 1、 关系型数据库对应用提供通用的操作接口&#xff0c;底层使用SQLite作为持久化存储引擎&#xff0c;支持SQLite具有的数据库特性&#xff0c;包括但不限于事务、索引、视图…...

Find My网球拍|苹果Find My技术与网球拍结合,智能防丢,全球定位

网球是球类运动项目之一&#xff0c;网球拍作为这项运动的必备工具&#xff0c;有木质球拍、铝合金球拍、钢质球拍和复合物&#xff08;尼龙、碳素&#xff09;球拍&#xff0c;任何材质的球拍均可用于比赛。网球拍由拍头、拍喉、拍柄组成&#xff0c;在使用时还需要配合网球线…...

windows环境下部署多个端口Tomcat服务和开机自启动设置保姆级教程

前言 本文主要介绍了 windows环境下&#xff0c;配置多个Tomcat设置不同端口启动服务。其实在思路上Linux上也是适用的&#xff0c;只是 Linux 上没有可视化客户端&#xff0c;会麻烦些&#xff0c;但总体的思路上是一样的。 注&#xff1a;文章中涉及些文字和图片是搬运了其他…...

科普文:一文搞懂jvm实战(四)深入理解逃逸分析Escape Analysis

概叙 Java 中的对象是否都分配在堆内存中&#xff1f; 好了太抽象了&#xff0c;那具体一点&#xff0c;看看下面这个对象是在哪里分配内存&#xff1f; public void test() { Object object new Object(); }这个方法中的object对象&#xff0c;是在堆中分配内存么&#xff1…...

中文大模型发展到哪一个阶段了?

中文大模型发展到哪一个阶段了&#xff1f; 近日&#xff0c;中文大模型综合性测评基准SuperCLUE&#xff0c;发布了上半年大模型中文综合评测报告。“百模大战”中&#xff0c;OpenAI的GPT-4o是表现最优秀的大模型&#xff0c;但国内大模型已将差缩小至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

前情提要&#xff1a;华为910b部署训练推理大模型&#xff0c;本人之前并没有接触过&#xff0c;所以&#xff0c;写此文档进行记录。 &#xff08;注意&#xff1a;版本适配很重要&#xff01;&#xff01;不然就像我一样走了好多坑~~~&#xff09; 首先&#xff0c;看一张图…...

legoloam算法环境配置和调试笔记

安装gtsam 参考 Ubuntu20.04安装gtsam记录_gtsam安装-CSDN博客 mkdir buildcd buildcmake .. make -...

如何用CSS3画一个三角形?

要用 CSS3 画一个三角形&#xff0c;可以利用元素的边框和透明边框的特性来实现。以下是一个简单的示例代码&#xff1a; .triangle {width: 0;height: 0;border-left: 50px solid transparent; /* 左边框为透明&#xff0c;控制三角形的左斜边 */border-right: 50px solid tr…...

不同型号的GD32 MCU如何区分?

大家是否碰到过以下应用场景&#xff1a;同一套软件代码希望跑在不同型号的GD32 MCU中&#xff0c;但有些地方需要根据MCU型号进行调整&#xff1f;或者上位机或其他MCU与GD32 MCU通信时需要知道对应的MCU型号是哪个&#xff1f; 此时&#xff0c;我们就需要了解如何获取以及区…...

关于windows下编译xLua插件的流程记录

1.工程准备 1.xLua工程&#xff1a;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工程&#xff1a;GitHub - chexiongsheng/build_xlua_with_libs…...

Hadoop简明教程

文章目录 关于HadoopHadoop拓扑结构Namenode 和 Datanode 基本管理启动Hadoop启动YARN验证Hadoop服务停止Hadoop停止HDFS Hadoop集群搭建步骤准备阶段Java环境配置Hadoop安装与配置HDFS格式化与启动服务测试集群安装额外组件监控与维护&#xff1a; 使用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&#xff0c;第343行。 listeners.environmentPrepared(bootstrapContext, environment);这里触发了事件ApplicationEnvironmentPreparedEvent 相…...

【源码开源】C#桌面应用开发:串口调试助手

c#桌面应用开发 1、环境搭建和工程创建&#xff1a;参照番茄定时器项目 工程创建参照 2、界面布局设计 3、具体功能函数 &#xff08;1&#xff09;端口扫描&#xff1a; private void btn_com_scan_Click(object sender, EventArgs e){//端口号扫描ReflashPortToComboBox(…...

malloc与free函数的用法(精简全面 · 一看即懂)

前言&#xff1a;Hello大家好&#x1f618;&#xff0c;我是心跳sy&#xff0c;今天为大家带来malloc函数与free函数的用法&#xff0c;我们一起来看看吧&#xff01; 目录 一、malloc函数 &#x1f4ab; 1、⭐️malloc函数对应的头文件⭐️ 2、⭐️malloc函数的作用⭐️ 3…...

强制升级最新系统,微软全面淘汰Win10和部分11用户

说出来可能不信&#xff0c;距离 Windows 11 正式发布已过去整整三年时间&#xff0c;按理说现在怎么也得人均 Win 11 水平了吧&#xff1f; 然而事实却是&#xff0c;三年时间过去 Win 11 占有率仅仅突破到 29%&#xff0c;也就跳起来摸 Win 10 屁股的程度。 2024 年 6 月 Wi…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析

LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...

手动给中文分词和 直接用神经网络RNN做有什么区别

手动分词和基于神经网络&#xff08;如 RNN&#xff09;的自动分词在原理、实现方式和效果上有显著差异&#xff0c;以下是核心对比&#xff1a; 1. 实现原理对比 对比维度手动分词&#xff08;规则 / 词典驱动&#xff09;神经网络 RNN 分词&#xff08;数据驱动&#xff09…...

leetcode 386. 字典序排数 中等

给你一个整数 n &#xff0c;按字典序返回范围 [1, n] 内所有整数。 你必须设计一个时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。 示例 1&#xff1a; 输入&#xff1a;n 13 输出&#xff1a;[1,10,11,12,13,2,3,4,5,6,7,8,9]示例 2&#xff1a; 输入&#xff1a;n 2…...

1.springmvc基础入门(一)

1.Spring MVC概念 Spring MVC 是 Spring Framework 提供的 Web 组件&#xff0c;全称是 Spring Web MVC&#xff0c;是⽬前主流的实现 MVC 设计模式的框架&#xff0c;提供前端路由映射、视图解析等功能。 Java Web 开发者必须要掌握的技术框架。 2.Spring MVC 功能 MVC&am…...

解决SQL Server SQL语句性能问题(9)——SQL语句改写(2)

9.4.3. update语句改写 与Oracle类似,SQL Server中,update语句被用户相关技术人员广泛应用于现实日常工作中。但是,有些情况下,尤其是海量数据场景中,update语句也许会带来性能方面的严重问题或极大隐患。因此,为了解决和消除update语句导致的性能问题或隐患,我们将需对…...