理解 Java Stream 的核心概念与工作原理
掌握 Stream 的创建方式与常用操作(中间操作与终端操作)
能够区分顺序流、并行流与无限流的使用场景
熟练运用 Stream 处理集合、文件及实际业务逻辑
明确 Stream 与传统集合的本质区别
Java 8 引入的 Stream API 提供了一种函数式、声明式的方式来处理数据集合。它允许开发者以链式调用的方式对数据进行过滤、映射、排序、聚合等操作,而无需编写繁琐的循环逻辑。
重要特性:Stream 不存储数据,它只是对数据源(如 List、数组、文件等)进行“流水线式”的处理。
核心特点
声明式编程:代码更简洁、意图更清晰
惰性求值:中间操作不会立即执行,直到遇到终端操作才触发计算
支持并行处理:通过 parallel() 或 parallelStream() 利用多核 CPU
不可变性:Stream 操作不会修改原始数据源
一次性使用:一个 Stream 只能被消费一次,重复使用会抛出异常
Stream 的处理过程分为三个阶段:
数据源:提供原始数据(如集合、数组、文件等)
中间操作:对数据进行转换、过滤等,返回新的 Stream(可链式调用)
终端操作:触发实际计算,产生最终结果(如列表、数值、输出等)

List<String> list = Arrays.asList("Java", "Python", "C++");
Stream<String> stream = list.stream();String[] arr = {"A", "B", "C"};
Stream<String> stream = Arrays.stream(arr);Stream.of()Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);需配合
limit()
// 迭代生成:1, 2, 3, 4, 5
Stream<Integer> infinite = Stream.iterate(1, n -> n + 1).limit(5);
// 随机生成
Stream<Double> randoms = Stream.generate(Math::random).limit(3);中间操作返回一个新的 Stream,支持链式调用。常见操作包括:
链式处理
List<Integer> numbers = Arrays.asList(5, 10, 20, 10, 30, 40);
numbers.stream()
.filter(n -> n > 10) // 保留大于 10 的
.map(n -> n * 2) // 翻倍
.distinct() // 去重
.sorted() // 升序排序
.forEach(System.out::println);输出:
40
60
80终端操作触发整个流水线的执行,并产生最终结果:
多种终端操作
List<String> names = Arrays.asList("Amit", "Riya", "Rohan", "Amit");
// 收集为 Set(自动去重)
Set<String> unique = names.stream().collect(Collectors.toSet());
// 统计以 'R' 开头的名字数量
long count = names.stream().filter(n -> n.startsWith("R")).count();
// 拼接所有名字
String joined = names.stream().reduce("", (a, b) -> a + b + " ");输出:
[Amit, Riya, Rohan]
Names starting with R: 2
Amit Riya Rohan Amit 默认的 Stream 类型,单线程依次处理元素。
list.stream().forEach(System.out::println);利用多线程并发处理,适合大数据量场景。
// 方式一:从集合创建
list.parallelStream().forEach(...);
// 方式二:转换已有流
stream.parallel().forEach(...);注意:并行流不保证元素处理顺序,且可能因线程切换带来额外开销,小数据集慎用。
通过 iterate() 或 generate() 创建无界序列,必须用 limit() 截断。
Stream.iterate(0, n -> n + 2).limit(5) // 0, 2, 4, 6, 8避免装箱 / 拆箱开销,提升性能:
IntStream:处理 int
LongStream:处理 long
DoubleStream:处理 double
IntStream.range(1, 5).forEach(System.out::println); // 1, 2, 3, 4简单说:Collection 是“数据容器”,Stream 是“数据处理器”
按行处理
try (Stream<String> lines = Files.lines(Paths.get("data.txt"))) {
List<String> upper5 = lines
.filter(s -> s.length() == 5)
.map(String::toUpperCase)
.collect(Collectors.toList());
}String[] words = {"Hello", "World", "Java"};
try (PrintWriter pw = new PrintWriter(Files.newBufferedWriter(Paths.get("output.txt")))) {
Stream.of(words).forEach(pw::println);
}优势:自动资源管理(try-with-resources)+ 函数式处理,代码更安全简洁
你有一组学生对象,包含姓名、年龄和成绩。你想找出 成绩大于等于 80 分 的学生,按年龄升序排列,然后只提取他们的 姓名,最终得到一个姓名列表
import java.util.*;
import java.util.stream.Collectors;
class Student {
private String name;
private int age;
private double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
// Getters
public String getName() { return name; }
public int getAge() { return age; }
public double getScore() { return score; }
@Override
public String toString() {
return name + " (age: " + age + ", score: " + score + ")";
}
}
public class StreamExample {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("Alice", 20, 85.5),
new Student("Bob", 19, 78.0),
new Student("Charlie", 22, 90.0),
new Student("Diana", 19, 82.5),
new Student("Eve", 21, 75.0)
);
List<String> highScorersNames = students.stream()
.filter(s -> s.getScore() >= 80) // 筛选出成绩 >=80 的学生
.sorted(Comparator.comparing(Student::getAge)) // 按年龄升序排序
.map(Student::getName) // 提取姓名
.collect(Collectors.toList()); // 收集为 List
System.out.println(highScorersNames);
// 输出: [Diana, Alice, Charlie]
// 解释: Bob 和 Eve 成绩 <80 被过滤;剩下三人中 Diana 和 Alice 都是19/20岁,Charlie 22岁
}
}此模式广泛应用于日志分析、报表生成、数据清洗等场景
Stream 是处理集合数据的现代方式,强调“做什么”而非“怎么做”
中间操作(filter/map/sorted)构建流水线,终端操作(collect/forEach)触发执行
并行流可提升性能,但需权衡线程开销与数据规模
原始类型流(IntStream 等)避免自动装箱,提升效率
Stream 适用于文件、数据库结果集、网络数据等多种数据源
为什么以下代码会抛出异常?如何修复?
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
stream.forEach(System.out::println); // ?在什么情况下,使用 reduce 比 collect 更合适?请举例说明。
尝试用 Stream 实现:从一个整数列表中找出所有偶数的平方和。