java的Stream流处理

news2025/5/14 0:11:32

Java Stream 流处理详解

Stream 是 Java 8 引入的一个强大的数据处理抽象,它允许你以声明式方式处理数据集合(类似于 SQL 语句),支持并行操作,提高了代码的可读性和处理效率。

一、Stream 的核心概念

1. 什么是 Stream

  • 不是数据结构:不存储数据,只是从数据源(集合、数组等)获取数据

  • 函数式风格:支持 lambda 表达式和方法引用

  • 延迟执行:许多操作(中间操作)不会立即执行,只有遇到终止操作才会执行

  • 可消费性:Stream 只能被消费一次,用完即失效

2. 操作类型

  • 中间操作(Intermediate Operations):返回 Stream 本身,可以链式调用(如 filter, map)

  • 终止操作(Terminal Operations):产生最终结果或副作用(如 forEach, collect)

二、创建 Stream 的多种方式

// 1. 从集合创建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream1 = list.stream();       // 顺序流
Stream<String> parallelStream = list.parallelStream(); // 并行流

// 2. 从数组创建
String[] array = {"a", "b", "c"};
Stream<String> stream2 = Arrays.stream(array);

// 3. 使用Stream.of()
Stream<String> stream3 = Stream.of("a", "b", "c");

// 4. 使用Stream.generate() 无限流
Stream<Double> randomStream = Stream.generate(Math::random).limit(5);

// 5. 使用Stream.iterate() 迭代流
Stream<Integer> iterateStream = Stream.iterate(0, n -> n + 2).limit(10);

三、常用的中间操作

1. 过滤操作

// filter(Predicate) 过滤符合条件的元素
List<String> filtered = list.stream()
    .filter(s -> s.startsWith("a"))
    .collect(Collectors.toList());

2. 映射操作

// map(Function) 将元素转换为其他形式
List<Integer> lengths = list.stream()
    .map(String::length)
    .collect(Collectors.toList());

// flatMap 将多个流合并为一个流
List<String> flatMapped = list.stream()
    .flatMap(s -> Stream.of(s.split("")))
    .collect(Collectors.toList());

3. 去重和排序

// distinct() 去重
List<String> distinct = list.stream().distinct().collect(Collectors.toList());

// sorted() 自然排序
List<String> sorted = list.stream().sorted().collect(Collectors.toList());

// sorted(Comparator) 自定义排序
List<String> customSorted = list.stream()
    .sorted((s1, s2) -> s2.compareTo(s1))
    .collect(Collectors.toList());

4. 其他中间操作

// limit(long) 限制元素数量
// skip(long) 跳过前N个元素
// peek(Consumer) 查看流中元素(主要用于调试)

四、常用的终止操作

1. 遍历操作

// forEach(Consumer) 遍历每个元素
list.stream().forEach(System.out::println);

2. 收集结果

// collect(Collector) 将流转换为集合或其他形式
List<String> collectedList = stream.collect(Collectors.toList());
Set<String> collectedSet = stream.collect(Collectors.toSet());
Map<String, Integer> map = stream.collect(
    Collectors.toMap(Function.identity(), String::length));

3. 聚合操作

// count() 计数
long count = list.stream().count();

// max/min(Comparator) 最大/最小值
Optional<String> max = list.stream().max(Comparator.naturalOrder());

// reduce 归约操作
Optional<Integer> sum = Stream.of(1, 2, 3).reduce(Integer::sum);

4. 匹配操作

// anyMatch 任意元素匹配
boolean anyStartsWithA = list.stream().anyMatch(s -> s.startsWith("a"));

// allMatch 所有元素匹配
boolean allStartsWithA = list.stream().allMatch(s -> s.startsWith("a"));

// noneMatch 没有元素匹配
boolean noneStartsWithZ = list.stream().noneMatch(s -> s.startsWith("z"));

五、数值流特化

Java 8 提供了专门的数值流,避免装箱拆箱开销:

// IntStream, LongStream, DoubleStream
IntStream intStream = IntStream.range(1, 100); // 1-99
DoubleStream doubleStream = DoubleStream.of(1.1, 2.2);

// 常用数值操作
int sum = IntStream.rangeClosed(1, 100).sum(); // 1-100的和
OptionalDouble avg = IntStream.of(1, 2, 3).average();

六、并行流处理

// 创建并行流
List<String> parallelProcessed = list.parallelStream()
    .filter(s -> s.length() > 1)
    .collect(Collectors.toList());

// 注意事项:
// 1. 确保操作是线程安全的
// 2. 避免有状态的操作
// 3. 数据量足够大时才使用并行流

七、收集器(Collectors)的高级用法

// 分组
Map<Integer, List<String>> groupByLength = list.stream()
    .collect(Collectors.groupingBy(String::length));

// 分区
Map<Boolean, List<String>> partition = list.stream()
    .collect(Collectors.partitioningBy(s -> s.startsWith("a")));

// 连接字符串
String joined = list.stream().collect(Collectors.joining(", "));

// 汇总统计
IntSummaryStatistics stats = list.stream()
    .collect(Collectors.summarizingInt(String::length));

八、实际应用示例

示例1:处理对象集合

List<Person> people = ...;

// 获取所有成年人的姓名列表
List<String> adultNames = people.stream()
    .filter(p -> p.getAge() >= 18)
    .map(Person::getName)
    .collect(Collectors.toList());

// 按城市分组
Map<String, List<Person>> byCity = people.stream()
    .collect(Collectors.groupingBy(Person::getCity));

// 计算每个城市的平均年龄
Map<String, Double> avgAgeByCity = people.stream()
    .collect(Collectors.groupingBy(
        Person::getCity,
        Collectors.averagingInt(Person::getAge)
    ));

示例2:文件处理

// 读取文件并处理
try (Stream<String> lines = Files.lines(Paths.get("data.txt"))) {
    long wordCount = lines
        .flatMap(line -> Arrays.stream(line.split("\\s+")))
        .filter(word -> word.length() > 0)
        .count();
} catch (IOException e) {
    e.printStackTrace();
}

九、注意事项

  1. 流只能消费一次:尝试第二次使用已关闭的流会抛出 IllegalStateException

  2. 避免修改源数据:流操作期间不应修改源集合

  3. 合理使用并行流:并非所有情况都适合并行,小数据量可能适得其反

  4. 注意自动装箱:数值操作尽量使用原始类型特化流(IntStream等)

  5. 延迟执行特性:没有终止操作,中间操作不会执行

Stream API 提供了一种高效、声明式的数据处理方式,是现代 Java 编程中不可或缺的工具。合理使用可以大幅提升代码的可读性和维护性。

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

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

相关文章

C PRIMER PLUS——第9节:动态内存分配、存储类别、链接和内存管理

目录 1.动态内存分配 1.1 malloc 函数 1.2 calloc 函数 1.3 realloc 函数 1.4 free 函数 1.5常见错误 1.6综合例题 2.C语言的内存结构 3.存储类别 3.1作用域&#xff08;Scope&#xff09; 3.2链接&#xff08;Linkage&#xff09; 3.3存储期&#xff08;Storage Du…

作业...

基础配置 RI R2 R3 R4 R5 例如R1 BGP配置 1,R1和R2之间使用直连接口IP地址来建立EBGP对等体关系 2、R2、R3、R4之间配置OSPF协议&#xff0c;保证各设备之间的网络互通&#xff0c;且通过重发布的方式发布路由 查看R2、R3、R4的OSPF路由表&#xff1a; \ R2、R3、R4使用环…

IC ATE集成电路测试学习——电流测试的原理和方法

电流测试 我们可以通过电流来判断芯片的工作状态时&#xff0c;首先先了解下芯片的电流是如何产生的。 静态电流 理论上&#xff0c;CMOS结构的芯片静态时几乎不耗电 CMOS基本结构&#xff1a;Pmos Nmos 串联当逻辑电平稳定时&#xff1a; ➜ 要么Pmos导通&#xff0c;Nmo…

快速理解动态代理

什么是动态代理(Java核心技术卷1的解释) 动态代理是一种运行时生成代理对象的技术&#xff0c;其本质是通过字节码增强在不修改原始类代码的前提下&#xff0c;动态拦截并扩展目标对象的行为。它通过代理对象对原始方法的调用进行拦截&#xff0c;并在方法执行前后注入自定义逻…

AugmentCode 非常昂贵的新定价

AugmentCode 现在的价格比 Cursor 和 Windsurf 的总和还要贵。 AugmentCode 曾是我开发工作流程的常用工具。出乎意料的是,他们改变了定价结构,让开发者们震惊不已。 原来的30 美元月费已经增长为50 美元月费,这是一个67%的增长。 改变我看法的不仅仅是价格上涨,还有他…

前端面试2

1. 面试准备 1. 建立自己的知识体系 思维导图ProcessOn框架Vue elementUI自查 https://zh.javascript.info/ 借鉴 https://juejin.cn/post/6844904103504527374http://conardli.top/blog/article/https://github.com/mqyqingfeng/Bloghttp://47.98.159.95/my_blog/#html 2.技能…

大疆卓驭嵌入式面经及参考答案

FreeRTOS 有哪 5 种内存管理方式&#xff1f; heap_1.c&#xff1a;这种方式简单地在编译时分配一块固定大小的内存&#xff0c;在整个运行期间不会进行内存的动态分配和释放。它适用于那些对内存使用需求非常明确且固定&#xff0c;不需要动态分配内存的场景&#xff0c;优点是…

架构进阶:74页数据架构设计总体规划方案【附全文阅读】

本文讨论了数据资源规划在信息化战略规划中的重要性&#xff0c;详细阐述了数据资源规划的方法与过程&#xff0c;包括系统架构、业务能力模型、数据架构等。 文章指出&#xff0c;数据资源规划需要梳理企业级数据模型&#xff0c;明确数据分布和流向&#xff0c;建立统一的数据…

情书大全v3.0.1

《情书大全》是一款致力于情书写作的手机应用程序&#xff0c;内置了丰富的情书范本及定制化服务。用户无论是想要倾诉爱意、交流友情还是传递亲情&#xff0c;都能在这款应用中寻得合适的情书样本。用户还可以根据自己的需求对模板进行编辑和调整&#xff0c;轻松创作出感人至…

基于OpenCV的人脸识别:LBPH算法

文章目录 引言一、概述二、代码实现1. 代码整体结构2. 导入库解析3. 训练数据准备4. 标签系统5. 待识别图像加载6. LBPH识别器创建7. 模型训练8. 预测执行9. 结果输出 三、 LBPH算法原理解析四、关键点解析五、改进方向总结 引言 人脸识别是计算机视觉领域的一个重要应用&…

鸿蒙 使用动画 简单使用

鸿蒙 使用动画 简单使用 动画就两个&#xff0c;属性动画和转场动画 属性动画只是组件的属性发生变化&#xff0c;而转场动画是指对将要出现或消失的组件做动画&#xff0c;而文档的其他动画只是给这两个动画效果锦上添花罢了 这篇文章简单介绍这两个动画&#xff0c;其他的…

arcgis和ENVI中如何将数据输出为tif

一、arcgis中转换为tif 右键图层&#xff1a; Data -> Export Data, 按照图示进行选择&#xff0c;选择tiff格式导出即可&#xff0c;还可以选择其他类型的格式&#xff0c;比如envi。 二、 ENVI中转换为tif File -> Save As -> Save As (ENVI, NITF, TIFF, DTED) …

RagFlow 完全指南(一):从零搭建开源大模型应用平台(Ollama、VLLM本地模型接入实战)

文章目录 1. 相关资源2. 核心特性3. 安装与部署3.1 环境准备3.2 部署RagFlow3.3 更新RagFlow3.4 系统配置 4. 接入本地模型4.1 接入 Ollama 本地模型4.1.1 步骤4.1.2 常见问题 4.2 接入 VLLM 模型 5. 应用场景6. 总结 1. 相关资源 官网GitHub文档中心 2. 核心特性 &#x1f…

计算机网络 4-2-1 网络层(IPv4)

2 IPv4分组 各协议之间的关系 IP协议(Internet Protocol, 网际协议)是互联网的核心&#xff01; ARP协议用于查询同一网络中的<主机IP地址&#xff0c;MAC地址>之间的映射关系 ICMP协议用于网络层实体之间相互通知“异常事件” IGMP协议用于实现IP组播 2.1 结构<首…

Python----机器学习(模型评估:准确率、损失函数值、精确度、召回率、F1分数、混淆矩阵、ROC曲线和AUC值、Top-k精度)

一、模型评估 1. 准确率&#xff08;Accuracy&#xff09;&#xff1a;这是最基本的评估指标之一&#xff0c;表示模型在测试集上正确 分类样本的比例。对于分类任务而言&#xff0c;准确率是衡量模型性能的直观标准。 2. 损失函数值&#xff08;Loss&#xff09;&#xff1…

Linux工作台文件操作命令全流程解析(高级篇之vim和nano精讲)

全文目录 1 简单易用的 Nano (入门之选)1.1 适用场景1.2 安装命令1.3 基础操作1.4 优点 2 功能强大的 Vim2.1 适用场景2.2 安装命令2.3 模式说明‌2.4 常用命令2.4.1 普通模式2.4.2 编辑模式2.4.3 可视模式2.4.4 命令行模式 3 参考文献 写在前面 作为运维或者研发&#xff0c;日…

大数据产品销售数据分析:基于Python机器学习产品销售数据爬虫可视化分析预测系统设计与实现

文章目录 大数据产品销售数据分析&#xff1a;基于Python机器学习产品销售数据爬虫可视化分析预测系统设计与实现一、项目概述二、项目说明三、研究意义四、系统总体架构设计总体框架技术架构数据可视化模块设计图后台管理模块设计数据库设计 五、开发技术介绍Flask框架Python爬…

VS2022 Qt配置Qxlsx

目录 1、下载QXlsx&#xff0c;并解压文件夹 ​编辑2、打开VS2022配置QXlsx 3、VS配置Qxslx库 方法一&#xff1a;常规方法 方法二&#xff1a;直接使用源码 方法三&#xff1a;将QXlsx添加到Qt安装目录&#xff08;暂时尝试未成功&#xff09; 1、下载QXlsx&#xff0c;…

OSPF案例

拓扑图&#xff1a; 要求&#xff1a; 1&#xff0c;R5为ISP&#xff0c;其上只能配置IP地址&#xff1b;R4作为企业边界路由器&#xff0c; 出口公网地址需要通过PPP协议获取&#xff0c;并进行chap认证 2&#xff0c;整个OSPF环境IP基于172.16.0.0/16划分&#xff1b;…

《用MATLAB玩转游戏开发》贪吃蛇的百变玩法:从命令行到AI对战

《用MATLAB玩转游戏开发&#xff1a;从零开始打造你的数字乐园》基础篇&#xff08;2D图形交互&#xff09;-&#x1f40d; 贪吃蛇的百变玩法&#xff1a;从命令行到AI对战 &#x1f3ae; 欢迎来到这篇MATLAB贪吃蛇编程全攻略&#xff01;本文将带你从零开始&#xff0c;一步步…