第 7 周:Lambda、方法引用与 Stream
本周目标
本周学会 JDK 8 之后的现代 Java 写法。完成后,应能够:
- 使用函数式接口和 Lambda 表达式替代匿名内部类
- 使用方法引用简化 Lambda
- 使用 Stream 完成过滤、映射、排序、去重和截取
- 使用
collect()把流结果收集为 List、Set、Map 和字符串 - 使用分组、分区和聚合完成统计报表
- 使用不可变集合避免意外修改
学习资料与范围
- 主课程:Java 零基础视频教程(下部)
- 视频范围:下部“函数式 & JDK8+”章节
| 学习模块 | 学习结果 |
|---|---|
| 函数式接口与 Lambda 表达式 | 能够用 Lambda 替代匿名内部类 |
| 方法引用与构造器引用 | 能够判断何时使用方法引用 |
| Stream 的创建、中间操作和终结操作 | 能够写出完整的数据处理流水线 |
| 收集结果与聚合统计 | 能够收集为集合、字符串和统计结果 |
| 不可变集合 | 能够创建并使用不可变集合 |
需要掌握的知识点
函数式编程基础
- 函数式接口的概念和
@FunctionalInterface Consumer、Supplier、Function、Predicate的用途和泛型含义- Lambda 的语法、参数和返回值推断规则
- 匿名内部类与 Lambda 的写法对比
- 方法引用的四种形式:静态方法、实例方法、对象方法、构造器引用
- 变量捕获限制:Lambda 中使用的外部局部变量必须是 final 或事实 final
Stream 基础
- Stream 与集合的区别:集合存数据,流处理数据
- 三步结构:创建流、中间操作、终结操作
- 创建流的方式:集合
stream()、数组Arrays.stream()、Stream.of() - 中间操作:
filter、map、distinct、sorted、limit、skip、flatMap - 终结操作:
forEach、count、collect、reduce、max、min - 惰性求值:中间操作不执行,终结操作才触发
- 流只能消费一次,重复使用会抛异常
收集与统计
collect(Collectors.toList())、toSet()、toMap()toMap()的键冲突问题和解决方式groupingBy()分组、partitioningBy()分区counting()、summingDouble()、averagingDouble()等下游收集器joining()拼接字符串并处理分隔符、前缀和后缀sorted()结合Comparator实现内存排序- 数值流
mapToInt()、mapToDouble()与sum()、average()、summaryStatistics()
不可变集合与使用原则
List.of()、Set.of()、Map.of()和List.copyOf()的特点- 不可变集合的修改报错和适用场景(常量、返回值保护)
- Stream 代码的可读性边界:逻辑复杂时保留传统循环
- 调试 Stream 链路的方法:拆分中间变量、先看中间结果
必做练习
- 匿名内部类改造:把
Comparator与Runnable的匿名内部类改写为 Lambda。 - 方法引用:把筛选、打印和构造学生对象的 Lambda 改写为方法引用,并说明选择理由。
- 筛选与映射:从学生列表中筛选出及格学生,映射为“姓名:总分”的字符串列表。
- 去重与排序:对班级名称去重并按名称排序输出。
- 对照练习:分别用循环和 Stream 实现同一统计需求,写出两种版本的代码并对比可读性。
- 收集为 Map:把学生列表收集为学号到学生的 Map,处理重复学号冲突。
- 分组统计:使用
groupingBy()统计每班人数和平均分。 - 聚合统计:使用
summaryStatistics()输出成绩的个数、总和、平均值、最大值和最小值。 - 排名报表:按总分降序取前三名,使用
joining()拼成多行文本并写入报表文件。 - 不可变集合:使用不可变集合保存班级名称常量,并记录一次修改失败的过程。
- 边界处理:统计空集合和全为不及格成绩时不出现除零或空指针异常。
本周综合任务:用 Stream 重写统计报表模块
把项目中的查询和统计方法改写为 Stream 写法,输出一份控制台报表。
要求:
- 使用 Stream 替换遍历加条件判断的统计代码
- 报表内容至少包含:班级人数、班级平均分、及格率、总分前三名、各科平均分
- 使用
groupingBy()加下游收集器完成分组统计,不使用多层嵌套循环 - 使用
Comparator和sorted()完成排名,复用第 6 周提取的比较器 - 使用
joining()生成对齐的文本报表,并保存为文件 - 至少保留一处传统循环写法,并在注释中说明保留原因
- 为每个统计方法补充单元测试,覆盖正常数据和空数据两种情况
本周产出
- Lambda 与方法引用练习代码
- Stream 常用操作练习代码
- 统计报表模块及生成的报表文件
- 循环版与 Stream 版对照代码
- 一份 Stream 常用方法速查笔记
完成检查
- 能够使用函数式接口和 Lambda 替代匿名内部类
- 能够识别并使用四种方法引用形式
- 能够写出创建、中间操作、终结操作完整的流处理链
- 能够把流结果收集为 List、Set、Map 和字符串
- 能够使用分组、分区和聚合完成统计
- 能够使用不可变集合保护数据
- 能够判断何时不适合使用 Stream
- 已完成统计报表模块的 Stream 改写并通过测试