
本文介绍如何使用 Java Stream API 将包含多科目成绩的学生数组,高效扁平化为单一的 Stream,涵盖双层 flatMap 的原理、正确写法及常见错误规避。
本文介绍如何使用 java stream api 将包含多科目成绩的学生数组,高效扁平化为单一的 `stream
在处理嵌套集合结构(如 StudenT[] → Map
以下是完整、可运行的实现代码:
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class StudenT {
private final String name;
private final Map<string list>> marks;
public StudenT(String name, Map<string list>> marks) {
this.name = name;
this.marks = marks;
}
public String getName() {
return name;
}
public Map<string list>> getMarks() {
return marks;
}
}
public class Lesson6 {
public static void main(String[] args) {
// 构建 Ann 的成绩
Map<string list>> markAnn = new HashMap();
markAnn.put("Physics", List.of(4, 4, 5));
markAnn.put("Mathematics", List.of(2, 3, 4));
// 构建 Kate 的成绩
Map<string list>> markKate = new HashMap();
markKate.put("Physics", List.of(1, 2, 3));
markKate.put("Mathematics", List.of(5, 5, 3));
StudenT[] students = {new StudenT("Ann", markAnn), new StudenT("Kate", markKate)};
// ✅ 正确方式:两层 flatMap
Stream<integer> allMarks = Arrays.stream(students)
.flatMap(student -> student.getMarks().values().stream()) // → Stream<list>>
.flatMap(Collection::stream); // → Stream<integer>
// 示例:打印全部成绩
allMarks.forEach(System.out::println);
// 输出:4 4 5 2 3 4 1 2 3 5 5 3(顺序取决于 map 迭代与 list 顺序)
}
}</integer></list></integer></string></string></string></string></string>
⚠️ 关键注意事项:
- ❌ 不要使用 Stream.of(students):它会创建 Stream
(即含一个数组元素的流),应改用 Arrays.stream(students) 获取 Stream ; - ❌ flatMap() 不能无参调用:原代码中 .flatMap() 缺少函数式参数,编译不通过;
- ✅ 第一层 flatMap 接收 Function
>>,提取每个学生所有科目的 List 并转为流; - ✅ 第二层 flatMap(Collection::stream) 将每个 List
转为 Stream 并合并,最终得到全体成绩的扁平流; - 若需去重或排序,可在链尾追加 .distinct() 或 .sorted();
- 如需按学生/科目分组统计,建议保留中间结构(如 Stream
>>),而非过早扁平化。
该模式适用于任意深度嵌套的集合转换场景,是 Java 函数式编程中处理“集合的集合”的标准范式。










