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

Stream API-怎么理解流

在Java中,Stream API(流式API)是Java 8引入的一种数据处理方式,它允许你以声明式、函数式风格处理数据集合(如List、Set、Map等)。


一、什么是"流"(Stream)?

想象一条传送带:

  • 数据源(如集合)像工厂的原料仓库

  • 流操作(如filter/map/sorted)像流水线上的加工环节

  • 最终结果(如collect)像包装好的成品

流的核心特点

  1. 非数据结构:不存储数据,只定义计算规则

  2. 惰性计算:中间操作不立即执行,直到遇到终止操作

  3. 可消费性:流只能被遍历一次(类似迭代器)


二、使用场景(何时用?)

在以下情况优先选择Stream API:

场景传统方式Stream API方式
数据过滤手动for循环+if判断.filter()
数据转换创建新集合+循环赋值.map()
聚合计算循环累加变量.reduce().sum()
并行处理手写线程池+任务拆分.parallelStream()
链式处理多层嵌套循环操作链(Pipeline)

典型用例

  • 集合元素过滤/转换

  • 分组/聚合统计(如按类别求和)

  • 大数据集并行处理

  • 复杂数据流水线操作


三、核心操作三阶段

1. 创建流(数据源 → 流)
// 从集合创建
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<String> stream = Stream.of("a", "b", "c");
2. 中间操作(加工数据 → 返回新流)
操作功能描述示例
filter()条件过滤.filter(s -> s.length() > 3)
map()元素转换.map(String::toUpperCase)
sorted()排序.sorted(Comparator.reverseOrder())
distinct()去重.distinct()
limit()截取前N个元素.limit(5)
3. 终止操作(获取结果 → 流终止)
操作功能描述示例
forEach()遍历消费.forEach(System.out::println)
collect()收集到集合.collect(Collectors.toList())
reduce()聚合计算.reduce(0, Integer::sum)
count()计数.count()
anyMatch()是否存在满足条件的元素.anyMatch(s -> s.contains("Java"))

四、实战代码示例

场景:Stream API筛选并转换字符串
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamVsTraditional {public static void main(String[] args) {// 原始数据List<String> words = Arrays.asList("apple", "banana", "cat", "dog", "elephant", "fox");System.out.println("原始数据: " + words);System.out.println();// 使用Stream API的写法List<String> streamResult = words.stream().filter(word -> word.length() > 3)  // 筛选长度大于3的单词.map(String::toUpperCase)           // 转换为大写.collect(Collectors.toList());      // 收集结果到新列表System.out.println("Stream API 结果: " + streamResult);// 使用传统循环的写法List<String> traditionalResult = new java.util.ArrayList<>();for (String word : words) {if (word.length() > 3) {            // 筛选长度大于3的单词traditionalResult.add(word.toUpperCase()); // 转换为大写并添加到结果列表}}System.out.println("传统循环 结果: " + traditionalResult);}
}
对比传统写法
List<String> traditionalResult = new ArrayList<>();
for (String word : words) {               // 遍历集合if (word.length() > 3) {              // 条件判断traditionalResult.add(             // 添加到结果集word.toUpperCase()            // 转换为大写);}
}
  • 手动创建结果集合

  • 使用for-each循环遍历

  • 使用if语句进行条件判断

  • 手动转换并添加结果


五、为什么使用Stream API?

优势说明
代码简洁减少50%以上样板代码
可读性强链式调用更符合思维逻辑
并行友好只需换.parallelStream()
避免状态无临时变量,减少bug
函数式风格易于组合复用操作

六、使用注意事项

  1. 流不可复用:终止操作后流即关闭

    Stream<String> stream = Stream.of("a", "b", "c");
    stream.forEach(System.out::println); // OK
    stream.count(); // 抛出IllegalStateException
  2. 避免副作用:不要在操作中修改外部状态

    // 错误示范(修改外部变量)
    List<String> result = new ArrayList<>();
    stream.filter(s -> s.startsWith("A")).forEach(s -> result.add(s)); // 不推荐// 正确做法
    List<String> result = stream.filter(s -> s.startsWith("A")).collect(Collectors.toList());
  3. 性能考量:小数据集用循环更高效,大数据集用并行流

    // 启用并行处理(适用于>10000条数据)
    BigDecimal total = orders.parallelStream()... 

总的来说

Stream API的核心概念

  1. 流(Stream)是什么?
    • 流是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列

    • 流本身不存储数据,只定义操作

    • 流操作是延迟执行的,只有需要结果时才执行

  2. 使用场景:
    • 数据过滤:从集合中筛选符合条件的元素

    • 数据转换:将元素映射为其他形式

    • 聚合计算:求和、平均、最大值等

    • 分组统计:按属性分组并计算统计值

    • 并行处理:利用多核处理器处理大数据集

  3. 流操作的三个阶段:
    • 创建流:通过集合、数组或生成器创建流

    • 中间操作:对流进行转换和过滤(返回新流)

    • 终止操作:产生最终结果或副作用

  4. 常用操作:
    • 中间操作:filter(), map(), sorted(), distinct(), limit()

    • 终止操作:forEach(), collect(), reduce(), count(), min(), max()

何时使用Stream API?

  1. 适合场景:
    • 需要对集合进行复杂的数据处理

    • 需要编写简洁的函数式代码

    • 需要并行处理大数据集

    • 需要链式数据处理管道

  2. 不适合场景:
    • 简单的遍历操作(传统for循环更直接)

    • 需要直接操作索引的情况

    • 需要修改原始集合中的数据

Stream API提供了一种更声明式、更函数式的数据处理方式,可以大大简化集合操作的代码,提高代码的可读性和可维护性。

http://www.lryc.cn/news/625988.html

相关文章:

  • Day13_【DataFrame数据组合merge连接】【案例】
  • Redis(11)如何通过命令行操作Redis?
  • 反向代理实现服务器联网
  • 人工神经网络MATLAB工具箱指南
  • Selenium自动化测试入门:cookie处理
  • electron进程间通信- 渲染进程与主进程双向通信
  • 如何用给各种IDE配置R语言环境
  • UGUI源码剖析(10):总结——基于源码分析的UGUI设计原则与性能优化策略
  • Ubuntu 和麒麟系统创建新用户 webapp、配置密码、赋予 sudo 权限并禁用 root 的 SSH 登录的详细
  • Python os 模块与路径操作:从基础到实战应用
  • 《AI 与人类创造力:是替代者还是 “超级协作者”?》​
  • 读《精益数据分析》:营收(Revenue)—— 设计可持续盈利模式
  • RabbitMQ:SpringAMQP 入门案例
  • Day22 顺序表与链表的实现及应用(含字典功能与操作对比)
  • 计算机大数据毕业设计推荐:基于Spark的气候疾病传播可视化分析系统【Hadoop、python、spark】
  • QT示例 基于Subdiv2D的Voronoi图实现鼠标点击屏幕碎裂掉落特效
  • jmetergrafanainfluxdb搭建压测监控平台
  • C# NX二次开发:操作按钮控件Button和标签控件Label详解
  • CentOS上安装Docker的完整流程
  • 可以一键生成PPT的AI PPT工具(最新整理)
  • AiPPT怎么样?好用吗?
  • Lecture 12: Concurrency 5
  • 大数据毕业设计选题推荐:护肤品店铺运营数据可视化分析系统详解
  • 106、【OS】【Nuttx】【周边】文档构建渲染:安装 Sphinx 扩展(下)
  • OptiTrack光学跟踪系统,提高机器人活动精度
  • 电影购票+票房预测系统 - 后端项目介绍(附源码)
  • Qt密码生成器项目开发教程 - 安全可靠的随机密码生成工具
  • SpringBoot-集成POI和EasyExecl
  • SpringAIAlibaba之基础功能和基础类源码解析(2)
  • LWIP的IP 协议栈