Java Stream 流(Stream API)详细讲解

Java Stream 流(Stream API)详细讲解

一、什么是 Stream 流

1.1 Stream 的本质

Stream 是 Java 8 引入的一套用于 集合数据处理的函数式 API。

需要明确几点:

  • Stream 不是数据结构
  • Stream 不存储数据
  • Stream 不修改原集合
  • Stream 关注的是 对数据的"计算过程"

可以把 Stream 理解为:

对集合中的数据,建立一条"流水线",数据依次经过各种操作,最终得到结果。


1.2 为什么要使用 Stream

在没有 Stream 之前,我们通常这样写代码:

java 复制代码
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = new ArrayList<>();

for (int x : list) {
    if (x % 2 == 0) {
        result.add(x * x);
    }
}

问题:

  • 代码冗长
  • 不利于并行计算

使用 Stream:

java 复制代码
List<Integer> result = list.stream()
        .filter(x -> x % 2 == 0)
        .map(x -> x * x)
        .toList();

二、Stream 的核心特点

2.1 三大特性

  1. 不存储数据
  2. 惰性执行
  3. 一次性消费

2.2 惰性执行示例

java 复制代码
list.stream()
    .filter(x -> {
        System.out.println("filter: " + x);
        return x > 2;
    });

上面代码 不会输出任何内容,因为:

没有终止操作,Stream 不会真正执行


三、Stream 的整体使用流程

Stream 使用分为 三步:

复制代码
数据源 → 中间操作 → 终止操作

示意:

java 复制代码
list.stream()        // 获取流
    .filter(...)     // 中间操作
    .map(...)        // 中间操作
    .forEach(...);   // 终止操作

四、创建 Stream 的方式

4.1 从集合创建

java 复制代码
List<Integer> list = List.of(1, 2, 3);
Stream<Integer> stream = list.stream();

4.2 从数组创建

java 复制代码
int[] arr = {1, 2, 3};
IntStream stream = Arrays.stream(arr);

4.3 使用 Stream.of

java 复制代码
Stream<String> stream = Stream.of("A", "B", "C");

4.4 创建无限流

java 复制代码
Stream<Integer> stream = Stream.iterate(0, x -> x + 2);
stream.limit(5).forEach(System.out::println);

五、中间操作(Intermediate Operations)

中间操作特点:

  • 返回新的 Stream
  • 支持链式调用
  • 不会立刻执行

5.1 filter(过滤)

java 复制代码
list.stream()
    .filter(x -> x > 3)
    .forEach(System.out::println);

5.2 map(映射)

java 复制代码
list.stream()
    .map(x -> x * 2)
    .forEach(System.out::println);

5.3 flatMap(扁平化)

java 复制代码
List<List<Integer>> lists = List.of(
    List.of(1, 2),
    List.of(3, 4)
);

lists.stream()
     .flatMap(List::stream)
     .forEach(System.out::println);

5.4 distinct(去重)

java 复制代码
list.stream()
    .distinct()
    .forEach(System.out::println);

5.5 sorted(排序)

java 复制代码
list.stream()
    .sorted()
    .forEach(System.out::println);

六、终止操作(Terminal Operations)

终止操作特点:

  • 触发 Stream 执行
  • 返回结果或副作用
  • 一个 Stream 只能有一个终止操作

6.1 forEach

java 复制代码
list.stream().forEach(System.out::println);

6.2 collect

java 复制代码
List<Integer> newList = list.stream()
        .filter(x -> x > 2)
        .collect(Collectors.toList());

6.3 reduce(归约)

java 复制代码
int sum = list.stream()
        .reduce(0, Integer::sum);

6.4 count / anyMatch / allMatch

java 复制代码
long count = list.stream().count();
boolean hasEven = list.stream().anyMatch(x -> x % 2 == 0);

七、并行流(Parallel Stream)

7.1 使用方式

java 复制代码
list.parallelStream()
    .map(x -> x * x)
    .forEach(System.out::println);

或:

java 复制代码
list.stream()
    .parallel()
    .forEach(System.out::println);

7.2 注意事项

  • 并行流 不保证顺序
  • 不适合 I/O 密集型任务
  • 共享变量可能产生线程安全问题

八、Stream 常见误区

8.1 Stream 会修改原集合?

不会。


8.2 Stream 可以重复使用?

不可以。

java 复制代码
Stream<Integer> s = list.stream();
s.forEach(System.out::println);
s.forEach(System.out::println); // 抛异常

九、Stream 与传统 for 循环对比

对比项 for 循环 Stream
编程风格 命令式 声明式
可读性 一般 高
并行能力 手动 内置
易错性 高 低

十、总结

  • Stream 是 数据处理工具,不是容器
  • 核心思想是 流水线 + 函数式编程
  • 牢记三步:创建 → 中间操作 → 终止操作
  • 合理使用,不要滥用并行流
相关推荐
Dwzun2 小时前
基于SpringBoot3+Vue3的油莎豆种植管理系统
java·前端·vue.js·spring boot·后端·python·计算机网络
学长毕设11 小时前
基于SpringBoot的实验室资产管理系统
java·spring boot·后端
zzu123zsw12 小时前
从臃肿的模板调用到声明式契约:深入 UniHttp 动态代理与多渠道生命周期扩展
java·spring boot·microsoft·unihttp
源码集结号13 小时前
云诊所门诊系统源码,基于SpringBoot+Vue.js架构,支持多租户设计与Docker容器化部署
java·spring boot·源码·医院信息系统·门诊系统·诊所系统
论文复现现场13 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
啃瓜子的松鼠14 小时前
泛微OAe9-后端二开异步调用
java
秋天的怀念_David14 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
外收内放15 小时前
Python基础语法练习题(73)
java·前端·python
Wang's Blog15 小时前
Java 项目实战: 交友项目 - 环信后台发送消息测试
java·交友
用户37215742613515 小时前
Java 操作 Word 脚注和尾注:添加、读取与删除
java