【Java】Stream API 全面详解
大家好,今天继续分享 Java 相关知识点,本篇来详细讲解 Stream API。Stream 是 Java 8 引入的核心特性之一,借助它我们可以用更简洁、优雅的方式处理集合、数组等数据源,告别繁琐的循环遍历,让代码可读性大幅提升。
一、什么是 Stream
Stream 可以理解为高级迭代器,它有几个核心特点:
- 流只能遍历一次,遍历结束后流就会被销毁,无法重复使用;
- 操作流必须依托数据源,常见数据源为数组、集合;
- Stream 支持链式调用,每一次中间操作都会返回新的流,原有流对象不会被改变;
- 流的操作分为两大类:中间操作和终端操作。
- 中间操作:可以连续多个,作用是对数据做过滤、转换等处理,执行后仍返回流,支持链式编程;
- 终端操作:只能有一个,必须放在所有操作的末尾,执行后流立即关闭,不再继续流转。
二、创建 Stream 流
日常开发中,主要从数组和集合两类数据源创建流,下面分场景演示代码。
1. 从数组创建流
可以使用 Arrays.stream() 或 Stream.of() 两种方式:
import java.util.Arrays;
import java.util.stream.Stream;
public class StreamDemo {
public static void main(String[] args) {
// 方式1:Arrays.stream() 创建流
Integer[] arr = {1, 2, 3, 4, 5};
Stream<Integer> stream1 = Arrays.stream(arr);
// 方式2:Stream.of() 创建流
Stream<Integer> stream2 = Stream.of(arr);
}
}
2. 从集合创建流
Java 8 给 Collection 接口新增了 stream() 方法,所有集合都可直接调用;同时还支持创建并发流parallelStream(),底层默认使用 ForkJoinPool.commonPool() 线程池,适合大数据量并行处理。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class StreamDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Java");
list.add("MySQL");
list.add("Linux");
// 普通串行流
Stream<String> stream = list.stream();
// 并发流
Stream<String> parallelStream = list.parallelStream();
}
}
三、常用流操作
结合中间操作、终端操作,讲解开发中最常用的 API,并搭配完整示例。
1. 去重 distinct ()(中间操作)
distinct() 会去除流中重复元素,返回新流,常搭配终端操作 count()(统计元素个数)使用。
import java.util.ArrayList;
import java.util.List;
public class StreamDemo {
public static void main(String[] args) {
List<Integer> numList = new ArrayList<>();
numList.add(1);
numList.add(2);
numList.add(2);
numList.add(3);
numList.add(3);
// 去重 + 统计元素总数
long count = numList.stream()
.distinct() // 中间操作:去重
.count(); // 终端操作:统计数量
System.out.println("去重后元素个数:" + count); // 输出:3
}
}
2. 过滤 filter ()(中间操作)
按照指定条件筛选元素,只保留符合条件的数据。
import java.util.ArrayList;
import java.util.List;
public class StreamDemo {
public static void main(String[] args) {
List<Integer> numList = List.of(1, 2, 3, 4, 5, 6);
// 筛选大于3的元素并遍历输出
numList.stream()
.filter(n -> n > 3) // 过滤条件
.forEach(System.out::println); // 终端操作:遍历
}
}
3. 映射 map ()(中间操作)
将流中的元素转换为新类型 / 新数据,比如类型转换、字段提取、数据运算。
import java.util.List;
public class StreamDemo {
public static void main(String[] args) {
List<String> strList = List.of("1", "2", "3", "4");
// 将字符串转为整数
strList.stream()
.map(Integer::parseInt) // 映射转换
.forEach(System.out::println);
}
}
4. 元素匹配(终端操作)
Stream 提供三种匹配方法,返回布尔值,属于终端操作:
anyMatch():任意一个元素满足条件,返回 true;allMatch():所有元素都满足条件,才返回 true;noneMatch():所有元素都不满足条件,才返回 true。
import java.util.List;
public class StreamDemo {
public static void main(String[] args) {
List<Integer> numList = List.of(2, 4, 6, 8);
// 是否存在大于5的元素
boolean any = numList.stream().anyMatch(n -> n > 5);
// 是否全部是偶数
boolean all = numList.stream().allMatch(n -> n % 2 == 0);
// 是否没有大于10的元素
boolean none = numList.stream().noneMatch(n -> n > 10);
System.out.println(any); // true
System.out.println(all); // true
System.out.println(none); // true
}
}
5. 归约组合 reduce ()(终端操作)
reduce() 用于将流中所有元素迭代合并、计算,常用于求和、求乘积、取最值等场景。
import java.util.List;
public class StreamDemo {
public static void main(String[] args) {
List<Integer> numList = List.of(1, 2, 3, 4, 5);
// 累加求和
numList.stream()
.reduce(Integer::sum)
.ifPresent(sum -> System.out.println("总和:" + sum)); // 输出:15
}
}
四、流转换为数组 / 集合
处理完流数据后,我们经常需要把流还原为数组或集合,主要使用 toArray() 和 collect() 方法。
1. 流转数组 toArray ()
import java.util.List;
public class StreamDemo {
public static void main(String[] args) {
List<String> list = List.of("Java", "MySQL", "Linux");
// 流转数组
String[] array = list.stream().toArray(String[]::new);
for (String s : array) {
System.out.println(s);
}
}
}
2. 流转集合 collect ()
借助 Collectors 工具类,可以将流收集为 List、Set 等不同集合:
import java.util.List;
import java.util.stream.Collectors;
public class StreamDemo {
public static void main(String[] args) {
List<Integer> numList = List.of(1, 2, 3, 4, 5);
// 过滤后重新收集为List集合
List<Integer> newList = numList.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println(newList); // 输出 [2, 4]
}
}
五、总结
Stream API 极大简化了集合与数组的处理逻辑,结合 Lambda 表达式后代码更加精简。使用时记住两个关键点:
- 中间操作延迟执行,必须配合终端操作才会触发整个流的执行;
- 流只能使用一次,终端操作执行完毕后流自动关闭,不可重复操作。
后续我会继续更新 Java 进阶相关内容,感兴趣的朋友可以持续关注,有问题欢迎在评论区交流~



