|
|
@@ -1,4 +1,4 @@
|
|
|
-# 20260803 课堂笔记 — 比较器排序(Comparable 自然排序 / Comparator 比较器排序)+ 集合工具类 Collections + 可变参数 Varargs + 20260731 课后作业解析
|
|
|
+# 20260803 课堂笔记 — 比较器排序(Comparable 自然排序 / Comparator 比较器排序)+ 集合工具类 Collections + 可变参数 Varargs + Lambda 表达式 + 20260731 课后作业解析
|
|
|
|
|
|
- **日期**:2026-08-03
|
|
|
- **项目**:`c260803`
|
|
|
@@ -15,11 +15,12 @@
|
|
|
4. [返回值规则与 compareTo/equals 一致性的官方推荐](#4-返回值规则与-comparetoequals-一致性的官方推荐)
|
|
|
5. [集合工具类 Collections](#5-集合工具类-collections)
|
|
|
6. [可变参数 Varargs(参数个数可变)](#6-可变参数-varargs参数个数可变)
|
|
|
-7. [20260731 课后作业解析:Map 集合基本操作与遍历](#7-20260731-课后作业解析map-集合基本操作与遍历)
|
|
|
-8. [20260731 课后作业解析:异常处理综合(自定义异常)](#8-20260731-课后作业解析异常处理综合自定义异常)
|
|
|
-9. [20260731 课后作业解析:匿名内部类 Comparator 排序](#9-20260731-课后作业解析匿名内部类-comparator-排序)
|
|
|
-10. [随堂练习要点](#10-随堂练习要点)
|
|
|
-11. [拓展阅读](#11-拓展阅读)
|
|
|
+7. [Lambda 表达式(函数式接口)](#7-lambda-表达式函数式接口)
|
|
|
+8. [20260731 课后作业解析:Map 集合基本操作与遍历](#8-20260731-课后作业解析map-集合基本操作与遍历)
|
|
|
+9. [20260731 课后作业解析:异常处理综合(自定义异常)](#9-20260731-课后作业解析异常处理综合自定义异常)
|
|
|
+10. [20260731 课后作业解析:匿名内部类 Comparator 排序](#10-20260731-课后作业解析匿名内部类-comparator-排序)
|
|
|
+11. [随堂练习要点](#11-随堂练习要点)
|
|
|
+12. [拓展阅读](#12-拓展阅读)
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -366,7 +367,94 @@ public class Demo03 {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 7. 20260731 课后作业解析:Map 集合基本操作与遍历
|
|
|
+## 7. Lambda 表达式(函数式接口)
|
|
|
+
|
|
|
+### 概念
|
|
|
+
|
|
|
+**Lambda 表达式**是 JDK 8 引入的、**简化匿名内部类**的一种写法,让代码更简洁、自由度更高。
|
|
|
+
|
|
|
+**标准格式**:
|
|
|
+```java
|
|
|
+(形式参数) -> {代码块}
|
|
|
+```
|
|
|
+- **形式参数**:多个参数用逗号分隔;没有参数就留空(如 `()`)
|
|
|
+- **`->`**:由英文减号 `-` 和大于号 `>` 组成,固定写法,代表**指向动作**
|
|
|
+- **{代码块}**:具体要做的事情,就是以前写在**方法体**中的内容
|
|
|
+
|
|
|
+**三要素**:形式参数、箭头、代码块。
|
|
|
+
|
|
|
+**为什么要有 Lambda 表达式?**
|
|
|
+Java 常被诟病"规范太多、太过冗长"。随着 JavaScript / Python / Go 等更灵活的语言流行,Java 为了迎合新的市场需求也开始求变,引入了 Lambda 表达式、函数式接口、Stream 流等更简练的写法。
|
|
|
+
|
|
|
+### 函数式接口(Functional Interface)
|
|
|
+
|
|
|
+**只有一个抽象方法**的接口叫**函数式接口**。Lambda 表达式本质是**另一种形式的匿名内部类**,但**只能用于简化函数式接口**——因为接口里只有一个需要重写的抽象方法,Lambda 的 `()` 才不会有歧义。
|
|
|
+
|
|
|
+```java
|
|
|
+// 来源:course/Swimming.java
|
|
|
+// Swimming 接口只有一个抽象方法 swim() → 函数式接口
|
|
|
+public interface Swimming {
|
|
|
+ void swim();
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 代码示例:三种实现方式的对比
|
|
|
+
|
|
|
+```java
|
|
|
+// 来源:course/SwimmingTest.java
|
|
|
+package course;
|
|
|
+
|
|
|
+public class SwimmingTest {
|
|
|
+ // 接收 Swimming 接口对象并调用其 swim() 方法
|
|
|
+ public static void getSwimming(Swimming s) {
|
|
|
+ s.swim();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ // 实现 Swimming 接口并重写 swim() 方法,以前有两种方式:
|
|
|
+ // 1、建立实现类,创建实现类对象(此处略)
|
|
|
+
|
|
|
+ // 2、创建 Swimming 的匿名内部类,并重写方法
|
|
|
+ getSwimming(new Swimming() {
|
|
|
+ @Override
|
|
|
+ public void swim() {
|
|
|
+ System.out.println("自由泳.....自由....免费");
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 3、使用 Lambda 表达式 —— 其实就是另一种形式的匿名内部类
|
|
|
+ getSwimming(() -> {
|
|
|
+ System.out.println("蛙游.....呱....呱");
|
|
|
+ });
|
|
|
+
|
|
|
+ // 匿名内部类:用变量接收
|
|
|
+ Swimming swimming = new Swimming() {
|
|
|
+ @Override
|
|
|
+ public void swim() {
|
|
|
+ System.out.println("自由泳.....自由....免费");
|
|
|
+ }
|
|
|
+ };
|
|
|
+ swimming.swim();
|
|
|
+
|
|
|
+ // Lambda 表达式:用变量接收
|
|
|
+ Swimming sw = () -> {
|
|
|
+ System.out.println("蛙游.....呱....呱");
|
|
|
+ };
|
|
|
+ sw.swim();
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 关键理解
|
|
|
+
|
|
|
+1. **Lambda = 匿名内部类的简化形式**:因为 `Swimming` 接口里**只有一个**需要重写的抽象方法,所以 `()` 能指向的就只有这一个抽象方法,`->` 指向的就是重写抽象方法的代码块内容。
|
|
|
+2. **使用前提**:Lambda 只能简化**函数式接口**(只有一个抽象方法),多抽象方法接口用 Lambda 会编译报错。
|
|
|
+3. **三要素对应**:`(形式参数)` → 重写方法的参数列表;`->` → 指向动作;`{代码块}` → 重写方法的方法体。
|
|
|
+4. **与匿名内部类的联系**:本节第 3 节 Comparator 正是用匿名内部类实现的,后续可以用 Lambda 进一步简化——如 `Collections.sort(list, (o1, o2) -> o1.getAge() - o2.getAge())`。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 8. 20260731 课后作业解析:Map 集合基本操作与遍历
|
|
|
|
|
|
### 作业要求回顾
|
|
|
|
|
|
@@ -439,7 +527,7 @@ public class MapDemo {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 8. 20260731 课后作业解析:异常处理综合(自定义异常)
|
|
|
+## 9. 20260731 课后作业解析:异常处理综合(自定义异常)
|
|
|
|
|
|
### 作业要求回顾
|
|
|
|
|
|
@@ -514,7 +602,7 @@ public class ScoreStatisticsDemo {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 9. 20260731 课后作业解析:匿名内部类 Comparator 排序
|
|
|
+## 10. 20260731 课后作业解析:匿名内部类 Comparator 排序
|
|
|
|
|
|
### 作业要求回顾
|
|
|
|
|
|
@@ -596,7 +684,7 @@ public class Student {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 10. 随堂练习要点
|
|
|
+## 11. 随堂练习要点
|
|
|
|
|
|
### 练习一:自然排序(Comparable)与比较器排序(Comparator)对比
|
|
|
|
|
|
@@ -672,6 +760,20 @@ public class Student {
|
|
|
2. 为什么有了可变参数还要方法重载?—— 参数**个数**不确定时用可变参数;参数**个数固定、类型不同**时重载更清晰
|
|
|
3. 如果方法同时有固定参数和可变参数,顺序有什么要求?—— 可变参数必须写在**参数列表最后**,否则编译报错
|
|
|
|
|
|
+### 练习七:Lambda 表达式(简化匿名内部类)
|
|
|
+
|
|
|
+**核心步骤**:
|
|
|
+1. 定义一个**函数式接口** `Swimming`(只有一个抽象方法 `void swim()`)
|
|
|
+2. 用**匿名内部类**实现并调用 `swim()`
|
|
|
+3. 用 **Lambda 表达式**实现同样的功能:`() -> { System.out.println("..."); }`
|
|
|
+4. 分别用「方法参数传递」和「变量接收」两种方式使用 Lambda
|
|
|
+5. 对比匿名内部类与 Lambda 的代码量
|
|
|
+
|
|
|
+**思考**:
|
|
|
+1. Lambda 表达式的三要素是什么?—— 形式参数、箭头 `->`、代码块
|
|
|
+2. 为什么 Lambda 只能用在**只有一个抽象方法**的接口上?—— 只有一个待重写方法,`()` 才能唯一确定指向它
|
|
|
+3. 本节第 3 节的 Comparator 匿名内部类能否改写成 Lambda?—— 可以,如 `(o1, o2) -> o1.getAge() - o2.getAge()`,后续 Stream 也会大量使用
|
|
|
+
|
|
|
### 随堂练习参考解答(已提供代码)
|
|
|
|
|
|
对应今日课堂练习的参考解答已写入授课代码:
|
|
|
@@ -739,7 +841,7 @@ treeSet = new TreeSet<>(new Comparator<Employee>() {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 11. 拓展阅读
|
|
|
+## 12. 拓展阅读
|
|
|
|
|
|
### 官方文档
|
|
|
|
|
|
@@ -750,6 +852,8 @@ treeSet = new TreeSet<>(new Comparator<Employee>() {
|
|
|
- [Collections 工具类 (JDK 17)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Collections.html)
|
|
|
- [List.of() (JDK 17)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html#of())
|
|
|
- [可变参数 Varargs(Oracle 教程)](https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html#varargs)
|
|
|
+- [Lambda 表达式(Oracle 教程)](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)
|
|
|
+- [函数式接口(Oracle 教程)](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#functional)
|
|
|
- [RuntimeException (JDK 17)](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/RuntimeException.html)
|
|
|
|
|
|
### 推荐阅读
|
|
|
@@ -762,7 +866,7 @@ treeSet = new TreeSet<>(new Comparator<Employee>() {
|
|
|
|
|
|
| 前置知识 | 当前知识 | 后续知识 |
|
|
|
|----------|----------|----------|
|
|
|
-| 匿名内部类(0727) | Comparator 匿名内部类实现 | Lambda 表达式(函数式接口) |
|
|
|
+| 匿名内部类(0727) | Lambda 表达式 / 函数式接口 | Stream 流、方法引用 |
|
|
|
| 集合体系与泛型(0729) | TreeSet / TreeMap 有序集合 | 红黑树底层(0731 已讲) |
|
|
|
| HashMap 基本操作(0731) | Map 综合练习(keySet/entrySet 遍历) | Map 与 Set 的互转、分组统计 |
|
|
|
| 异常处理(0728) | 自定义异常 + 多 catch 块 | 异常链、try-with-resources |
|