Java Stream 流详解

Java Stream 流详解

1. 什么是 Stream?

Stream(流) 是 Java 8 引入的一个强大工具,用于简化集合处理操作。

它提供了一种更**声明式(类似 SQL 查询)**的方式处理数据,使代码更简洁可读。

Stream 不是集合,也不存储数据;它是对数据源的一种 操作视图


2. Stream 的特点

  • 不存储数据:Stream 只是"看着"集合的数据做操作。
  • 函数式风格:大量使用 lambda 表达式。
  • 惰性求值:大多数操作不会立刻执行,只有遇到终止操作才执行。
  • 一次性:一个 Stream 只能消费一次。
  • 可并行 :通过 parallelStream() 自动利用多核 CPU。

3. Stream 的常见操作分类

Stream 操作分为两类:

◆ 中间操作(返回 Stream,本身不执行)

常见中间操作:

方法 作用
filter() 过滤
map() 映射(转换)
sorted() 排序
limit() 限制前 n 个
skip() 跳过前 n 个
distinct() 去重
mapToInt() 转换为 IntStream

中间操作是惰性的:不遇到终止操作不会真正执行。


◆ 终止操作(触发执行)

常见终止操作:

方法 作用
forEach() 遍历
collect() 收集成集合
count() 计数
findFirst() 查找第一个
findAny() 查找任意一个(并行时效果好)
anyMatch() 是否有任意一个匹配
allMatch() 是否所有都匹配

4. Stream 使用流程(三步走)

① 获取 Stream → ② 中间操作 → ③ 终止操作

例子:

复制代码
List<String> list = Arrays.asList("a", "b", "c");

list.stream()
    .filter(s -> s.equals("a"))  // 中间操作
    .forEach(System.out::println); // 终止操作

5. 获取 Stream 的方式

① 从集合创建

复制代码
list.stream();
list.parallelStream();

② 从数组创建

复制代码
Arrays.stream(arr);

③ 从静态方法 Stream.of()

复制代码
Stream.of(1, 2, 3);

6. 常见使用案例总结

示例1:过滤 filter

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

list.stream()
    .filter(n -> n % 2 == 0)
    .forEach(System.out::println);

示例2:映射 map

复制代码
List<String> list = Arrays.asList("Java", "Python", "Go");

list.stream()
    .map(String::toUpperCase)
    .forEach(System.out::println);

示例3:排序 sorted

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

示例4:收集 collect

复制代码
List<Integer> even = list.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());

示例5:去重 distinct

复制代码
Stream.of(1,2,2,3,3,3)
    .distinct()
    .forEach(System.out::println);

示例6:统计 count

复制代码
long count = list.stream().count();

7. Stream 的并行 parallelStream()

非常适合集合数据量大时使用。

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

自动利用 CPU 多核,提高性能。


8. Stream 和普通 for 的对比

对比点 for 循环 Stream
可读性 逐句命令式 声明式、高可读
支持并行 手动操作线程 自动并行
转换/过滤 自己写代码 内置 API
Lambda 不支持 完全支持

一般在处理 集合流水线操作 时 Stream 更优雅、更安全、更易维护。


9. 注意点

  1. Stream 只能消费一次
  2. 中间操作不会立即执行
  3. 使用 parallelStream() 时注意线程安全
  4. Stream 不是万能,有些场景普通 for 反而更高效

🚀 一、Stream 只能消费一次是什么意思?

✔ 1. Stream 是"一次性"的流水线

你可以把 Stream 想成:
一次从头到尾的处理流程(Pipeline)

一旦你执行了终止操作(forEach、collect、count 等),

这个 Stream 就已经"用完"了,不能再用。

就像:

  • 水流过水管以后,不能再把同一股水装回去重新流
  • 用过的快递面单不能重复用

📌 示例(错误用法)

复制代码
Stream<String> stream = List.of("a", "b", "c").stream();

stream.forEach(System.out::println);

stream.forEach(System.out::println); // ❌ 会报错

第二次使用会报错:

复制代码
java.lang.IllegalStateException: stream has already been operated upon or closed

✔ 2. 为什么不能用第二次?

因为:

  • Stream 是对集合的一次遍历视图
  • 执行终止操作时,它内部的迭代器就被关闭
  • 关闭后就不能再遍历

这叫:单次消费(one-shot)


🚀 二、:: 是什么?(方法引用 Method Reference)

:: 是 Java 8 的语法糖,用于引用方法

和 Lambda 表达式作用类似,但更简洁。


✔ 1. 最常见的用法:System.out::println

等价于:

复制代码
x -> System.out.println(x)

也就是:

  • "把元素 x 打印出来"
  • :: 只是引用了一个已有方法,而不是写新的 lambda

✔ 2. :: 的四种常见形式

写法 含义 等价 lambda
ClassName::staticMethod 静态方法引用 x -> ClassName.staticMethod(x)
object::instanceMethod 某对象的实例方法 x -> object.instanceMethod(x)
ClassName::instanceMethod 由实例调用的方法 (obj, x) -> obj.instanceMethod(x)
ClassName::new 构造方法引用 () -> new ClassName()

✔ 3. 一些常见例子

① 静态方法引用

复制代码
Stream.of("1", "2", "3")
    .map(Integer::parseInt); 

等价于:

复制代码
.map(s -> Integer.parseInt(s))

② 实例方法引用

复制代码
List<String> list = List.of("a", "b");

list.forEach(System.out::println);

等价于:

复制代码
list.forEach(x -> System.out.println(x));

③ 构造方法引用

复制代码
Stream.generate(Person::new);

等价于:

复制代码
Stream.generate(() -> new Person());

🚀 三、最容易理解的大总结

✔ Stream 只能消费一次

  • 执行终止操作后就关闭
  • 不能重复遍历
  • 必要时重新创建 Stream:list.stream()

✔ :: 是方法引用

  • 用于简化 lambda 表达式
  • 常见例子:System.out::println
  • 代表"调用这个方法,不用自己写函数体"
相关推荐
渡我白衣1 小时前
哈希的暴力美学——std::unordered_map 的底层风暴、扩容黑盒与哈希冲突终极博弈
java·c语言·c++·人工智能·深度学习·算法·哈希算法
信码由缰1 小时前
Java记录类入门:简化的以数据为中心的Java编程
java
IT界的渣1 小时前
IDEA Maven打包加速工具 mvnd
java·maven·intellij-idea·mvnd
c***93771 小时前
Spring Security 官网文档学习
java·学习·spring
z***3351 小时前
SpringBoot项目中读取resource目录下的文件(六种方法)
spring boot·python·pycharm
x***01061 小时前
Java框架SpringBoot(一)
java·开发语言·spring boot
T***74251 小时前
SpringMVC新版本踩坑[已解决]
java
Kuo-Teng1 小时前
Mastering High-Concurrency Data Processing: A Deep Dive into BufferTrigger
java·数据结构
JHC0000001 小时前
x 的平方根
开发语言·爬虫·python