Java流式处理-Steam详解

news2025/5/24 5:56:31

Java 8 引入的 Stream API 是一种强大的处理集合数据的工具,它允许你以声明式方式处理数据集合(如 List、Set 等),并支持多种聚合操作(如过滤、映射、排序、归约等)。Stream API 可以显著提高代码的可读性和简洁性,同时支持并行处理以提升性能。

一、Stream 基础概念

1. 什么是 Stream?
  • Stream 是一种针对集合数据的高级抽象,它不存储数据,而是定义了一系列对数据源(如集合、数组)的操作。
  • Stream 操作是惰性的,只有在终止操作被调用时才会执行。
  • Stream 可以是串行的或并行的,并行流利用多线程提高处理大数据的效率。
2. Stream 的特点
  • 不改变数据源:Stream 操作不会修改原始数据,而是返回一个新的 Stream。
  • 一次性使用:Stream 只能被消费一次,消费后需要重新创建。
  • 延迟执行:中间操作(如 filter、map)只会记录操作,不会立即执行,直到终止操作(如 collect、forEach)被调用。

二、Stream 的创建

1. 从集合创建

java

List<String> list = Arrays.asList("apple", "banana", "cherry");
Stream<String> stream = list.stream(); // 串行流
Stream<String> parallelStream = list.parallelStream(); // 并行流
2. 从数组创建

java

int[] array = {1, 2, 3, 4, 5};
IntStream intStream = Arrays.stream(array);
3. 使用 Stream.of ()

java

Stream<String> stream = Stream.of("apple", "banana", "cherry");
4. 创建无限流

java

// 生成无限序列(0, 2, 4, 6...)
Stream<Integer> evenNumbers = Stream.iterate(0, n -> n + 2);
// 生成随机数流
Stream<Double> randoms = Stream.generate(Math::random);

三、Stream 的中间操作

中间操作返回一个新的 Stream,允许链式调用多个操作。常见的中间操作包括:

1. 过滤元素:filter()

java

List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
List<String> filtered = fruits.stream()
    .filter(fruit -> fruit.startsWith("a")) // 保留以 'a' 开头的元素
    .collect(Collectors.toList()); // [apple]
2. 映射元素:map()

java

List<Integer> numbers = Arrays.asList(1, 2, 3);
List<Integer> squared = numbers.stream()
    .map(n -> n * n) // 平方每个元素
    .collect(Collectors.toList()); // [1, 4, 9]
3. 扁平化嵌套结构:flatMap()

java

List<List<Integer>> nested = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4)
);
List<Integer> flattened = nested.stream()
    .flatMap(List::stream) // 将嵌套列表展开为单个流
    .collect(Collectors.toList()); // [1, 2, 3, 4]
4. 排序:sorted()

java

List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
List<String> sorted = names.stream()
    .sorted() // 自然排序
    .collect(Collectors.toList()); // [Alice, Bob, Charlie]
5. 去重:distinct()

java

List<Integer> duplicates = Arrays.asList(1, 2, 2, 3, 3, 3);
List<Integer> unique = duplicates.stream()
    .distinct() // 去重
    .collect(Collectors.toList()); // [1, 2, 3]
6. 截断:limit() 和 skip()

java

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limited = numbers.stream()
    .limit(3) // 取前3个元素
    .collect(Collectors.toList()); // [1, 2, 3]

List<Integer> skipped = numbers.stream()
    .skip(2) // 跳过前2个元素
    .collect(Collectors.toList()); // [3, 4, 5]

四、Stream 的终止操作

终止操作触发 Stream 的执行并返回最终结果。常见的终止操作包括:

1. 收集结果:collect()

java

// 收集到 List
List<String> resultList = stream.collect(Collectors.toList());

// 收集到 Set
Set<String> resultSet = stream.collect(Collectors.toSet());

// 收集到 Map
Map<Integer, String> map = stream
    .collect(Collectors.toMap(
        s -> s.length(), // key: 字符串长度
        s -> s,          // value: 字符串本身
        (existing, replacement) -> existing // 处理键冲突的策略
    ));
2. 遍历元素:forEach()

java

stream.forEach(System.out::println); // 打印每个元素
3. 聚合操作:reduce()

java

// 求和
int sum = numbers.stream()
    .reduce(0, (a, b) -> a + b); // 初始值为0,累加所有元素

// 求最大值
Optional<Integer> max = numbers.stream()
    .reduce(Integer::max); // 返回 Optional 避免空指针
4. 匹配元素:anyMatch()allMatch()noneMatch()

java

boolean anyStartsWithA = stream.anyMatch(s -> s.startsWith("A")); // 是否存在以 'A' 开头的元素
boolean allStartsWithA = stream.allMatch(s -> s.startsWith("A")); // 是否所有元素都以 'A' 开头
boolean noneStartsWithA = stream.noneMatch(s -> s.startsWith("A")); // 是否没有元素以 'A' 开头
5. 查找元素:findFirst()findAny()

java

Optional<String> first = stream.findFirst(); // 返回第一个元素(可能为空)
Optional<String> any = stream.findAny(); // 返回任意元素(并行流中可能随机返回)
6. 统计:count()min()max()

java

long count = stream.count(); // 元素个数
Optional<Integer> min = numbers.stream().min(Integer::compareTo); // 最小值
Optional<Integer> max = numbers.stream().max(Integer::compareTo); // 最大值

五、并行流(Parallel Stream)

并行流利用多核处理器并行执行 Stream 操作,适用于大数据集的高效处理。

1. 创建并行流

java

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> parallelStream = numbers.parallelStream(); // 直接创建并行流
Stream<Integer> parallelStream2 = numbers.stream().parallel(); // 将串行流转换为并行流
2. 并行流示例

java

long sum = numbers.parallelStream()
    .mapToInt(Integer::intValue)
    .sum(); // 并行求和
3. 注意事项
  • 线程安全:并行流操作涉及多线程,确保操作的数据源和中间操作是线程安全的。
  • 适用场景:对于小数据集或操作本身开销不大的情况,并行流可能比串行流更慢(线程调度开销)。
  • 顺序问题:并行流不保证处理顺序,若需要顺序性,可使用 forEachOrdered() 替代 forEach()

六、Collectors 工具类

Collectors 是一个实用工具类,提供了各种收集器(Collector),用于将 Stream 结果收集到不同的数据结构中。

1. 分组:groupingBy()

java

// 按字符串长度分组
Map<Integer, List<String>> groups = stream
    .collect(Collectors.groupingBy(String::length));
2. 分区:partitioningBy()

java

// 按条件分区(偶数和奇数)
Map<Boolean, List<Integer>> partitioned = numbers.stream()
    .collect(Collectors.partitioningBy(n -> n % 2 == 0));
3. 连接字符串:joining()

java

String joined = stream
    .collect(Collectors.joining(", ")); // 用逗号连接元素
4. 统计:summarizingInt()

java

IntSummaryStatistics stats = numbers.stream()
    .collect(Collectors.summarizingInt(Integer::intValue));
// stats 包含 count, sum, min, max, average

七、Stream 与 Lambda 表达式结合

Stream API 与 Lambda 表达式紧密结合,使代码更简洁。例如:

java

// 传统方式
List<String> filtered = new ArrayList<>();
for (String fruit : fruits) {
    if (fruit.startsWith("a")) {
        filtered.add(fruit);
    }
}

// Stream + Lambda 方式
List<String> filtered = fruits.stream()
    .filter(fruit -> fruit.startsWith("a"))
    .collect(Collectors.toList());

八、常见使用场景

1. 数据过滤与转换

java

List<Product> products = getProducts();
List<String> productNames = products.stream()
    .filter(p -> p.getPrice() > 100) // 过滤价格大于100的产品
    .map(Product::getName) // 提取产品名称
    .collect(Collectors.toList());
2. 聚合统计

java

double averagePrice = products.stream()
    .mapToDouble(Product::getPrice)
    .average() // 计算平均价格
    .orElse(0.0);
3. 并行处理

java

// 并行计算所有产品的总价格
double totalPrice = products.parallelStream()
    .mapToDouble(Product::getPrice)
    .sum();

总结

Java Stream API 通过声明式方式处理集合数据,使代码更简洁、易读,并支持并行处理以提高性能。关键要点:

  • 中间操作(如 filtermap)返回新的 Stream,支持链式调用。
  • 终止操作(如 collectforEach)触发执行并产生结果。
  • 并行流适用于大数据集的高效处理,但需注意线程安全和适用场景。
  • Collectors 工具类提供丰富的收集器,用于结果转换和聚合。

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

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

相关文章

windows服务器部署jenkins工具(一)

jenkins作为一款常用的构建发布工具&#xff0c;极大的简化了项目部署发布流程。jenkins通常是部署在linux服务上&#xff0c;今天给大家分享的是windows服务器上如何搭建jenkins发布工具。 1.首先第一步还是看windows安装docker 这篇文章哈&#xff0c;当然也可以不采用docke…

基于51单片机和8X8点阵屏、独立按键的飞行躲闪类小游戏

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、8X8点阵屏2、独立按键3、定时器04、定时器1 四、主函数总结 系列文章目录 前言 用的是普中A2开发板。 【单片机】STC89C52RC 【频率】12T11.0592MHz 【外设】8X8点阵屏、独立按键 效果查看/操作演示&#xff…

告别“盘丝洞”车间:4-20mA无线传输如何重构工厂神经网?

4-20ma无线传输是利用无线模块将传统的温度、压力、液位等4-20mA电流信号转换为无线信号进行传输。这一技术突破了有线传输的限制&#xff0c;使得信号可以在更广泛的范围内进行灵活、快速的传递&#xff0c;无线传输距离可达到50KM。达泰4-20ma无线传输模块在实现工业现场应用…

VMware虚拟机突然无法ssh连接

遇到的情况&#xff1a; 功能全部正常的情况下&#xff0c;没有修改任何配置&#xff0c;重启电脑之后无法ssh连接 其实不太可能的可能原因&#xff1a; 1、虚拟机内部sshd服务未运行 systemctl status sshd systemctl start sshd 2、检查SSH端口监听 netstat -an | grep :…

班迪录屏--解决视频剪辑时声音和画面不同步的问题

原文网址&#xff1a;班迪录屏--解决视频剪辑时声音和画面不同步的问题_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何用班迪录屏解决视频剪辑时声音和画面不同步的问题。 问题描述 我用班迪录屏录了视频&#xff0c;用剪映进行剪辑&#xff0c;结果发现在剪辑时声音和画面…

Git上传项目到GitHub

Git上传项目到GitHub 下载Git客户端配置Git设置GitHub上传本地项目到Github 下载Git客户端 网址&#xff1a;Git Windows客户端。选择Standalone Installer(单独安装程序)&#xff0c;并点击64bit Git for Windows Setup(64位Git for Windows安装程序)进行下载。然后一路默认选…

【工具】Quicker/VBA|PPT 在指定位置添加有颜色的参考线

文章目录 效果展示使用方式技术原理更多原理ActivePresentation.Guides 概述主要属性和方法使用示例添加水平参考线添加垂直参考线删除所有参考线获取参考线数量 注意事项 致谢 效果展示 先展示效果&#xff1a; Quicker 动作&#xff1a;VBA 添加参考线 - Quicker 动作 使用…

第34节:迁移学习中的特征提取方法

迁移学习中的特征提取方法:原理、技术与应用 1. 迁移学习与特征提取概述 迁移学习(Transfer Learning)作为机器学习领域的重要范式 通过将源领域(source domain)学到的知识迁移到目标领域(target domain),有效解决了传统机器学习需要大量标注数据的瓶颈问题。 在迁…

(万字长文)Django数据库操作——ORM:数据交互显示前端网页

&#x1f31f; 如果这篇文章触动了你的心弦&#xff0c;请不要吝啬你的支持&#xff01; 亲爱的读者&#xff0c; 感谢你花时间阅读这篇分享。希望这里的每一个字都能为你带来启发或是让你会心一笑。如果你觉得这篇文章有价值&#xff0c;或者它解决了你一直以来的一个疑问&a…

实验-使用递归计算阶乘-RISC-V(计算机组成原理)

目录 一、实验内容 二、实验步骤 三、实验效果 四、实验环境 五、实验小结和思考 一、实验内容 一个典型的计算阶乘的递归过程如下图所示&#xff1a; 在这个任务中&#xff0c;一份汇编代码的框架“task4-阶乘”你需要使用RISC-V或MIPS汇编程序以递归的形式解决这个问题。…

ISO 26262-5 评估硬件架构度量值

两种硬件架构的度量&#xff0c; 用于评估相关项架构应对随机硬件失效的有效性。 应评估&#xff08;评估仅限于ASIL (B)、 C 和 D 的安全目标&#xff09; 1 应将按照附录 C 单点故障度量和潜伏故障度量的诊断覆盖率来评估 2 应结合残余故障和相关的潜伏故障来预估安全机制…

【Qt开发】显示类控件——QLCDNumber

目录 1&#xff0c;QLCDNumber的说明 2&#xff0c;QLCDNumber的运用 1&#xff0c;QLCDNumber的说明 QLCDNumer 是一个专门用来显示数字的控件。它类似于 "老式计算器" 的效果。它的核心属性如下&#xff1a; 2&#xff0c;QLCDNumber的运用 定时器 运用QLCDNumb…

音频AAC编码与RV1126的AENC模块的讲解

一.音频编码的原理 AAC编码的基本概念 AAC&#xff08;Advanced Audio Coding&#xff09;是一种高级音频编码格式&#xff0c;旨在提供比MP3更高的音质和更低的比特率。AAC是MPEG-2和MPEG-4标准的一部分&#xff0c;广泛应用于音乐、视频流媒体和广播等领域 音频为什么要进…

vue页面目录菜单有些属性是根据缓存读取的。如果缓存更新了。希望这个菜单也跟着更新。

父组件中有两个子组件。如果在B组件数据更新之后。A组件也跟着一起改变呢&#xff1f;如图如果我右边基本信息里面勾选了高血压&#xff0c;左侧菜单里面也要立刻出现一个高血压随访菜单&#xff0c;如果我取消勾选了左侧菜单就去掉。 左侧菜单的显示和隐藏的数据实际上是放在…

在TIA 博途中下载程序时找不到对应的网卡怎么办?

1. 检查物理连接 确认网线已正确连接PLC和PC&#xff0c;接口指示灯正常。 尝试更换网线或交换机端口&#xff0c;排除硬件故障。 2. 确认网卡驱动已安装 设备管理器检查&#xff1a; 右键点击“此电脑” → “管理” → “设备管理器”。 展开“网络适配器”&#xff0c;确…

《量子计算实战》PDF下载

内容简介 在加密、科学建模、制造物流、金融建模和人工智能等领域&#xff0c;量子计算可以极大提升解决问题的效率。量子系统正变得越来越强大&#xff0c;逐渐可用于生产环境。本书介绍了量子计算的思路与应用&#xff0c;在简要说明与量子相关的科学原理之后&#xff0c;指…

Linux入门(部分基础相关知识+常用命令+权限)

目录 1.基础背景了解 2、基本操作系统、linux相关知识 1.操作系统是一款用来管理软硬件资源的软件。 2.对于一个文件来说&#xff0c;是由文件内容文件属性构成的。空文件&#xff08;内容为空&#xff09;也占磁盘空间。 3.linux下的目录结构 4.linux下的删除 5.环境 6…

海拔案例分享-实践活动报名测评小程序

大家好&#xff0c;今天湖南海拔科技想和大家分享一款实践活动报名测评小程序&#xff0c;客户是长沙一家专注青少年科创教育的机构&#xff0c;这家机构平时要组织各种科创比赛、培训课程&#xff0c;随着学员增多&#xff0c;管理上的问题日益凸显&#xff1a;每次组织活动&a…

cmd里可以使用npm,vscode里使用npm 报错

cmd里可以使用npm,vscode里使用npm 报错 报错提示原因解决方法 报错提示 npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1&#xff0c;因为在此系 统上禁止运行脚本。有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/ fwlink/?LinkID135170 中的 about_Executi…

JAVA开发工具延长方案

亲测稳定的延长方案与避坑指南 真的搞不懂了&#xff0c;说点专业的术语竟然成了 QINQUAN。那就直接点&#xff0c;把这个方案带给需要的开发者。 延长工具直通车 保姆级教程 延长方案https://mp.weixin.qq.com/s/uajM2Y9Vz6TnolzcLur_bw还是让大家看看&#xff0c;发什么会被…