Forráskód Böngészése

docs: 更新20260729课堂笔记+新增集合框架练习——同步代码变更:新增ArrayList常用方法速查表(add/get/set/remove/size/isEmpty/contains/indexOf/toArray/getFirst/getLast);基于笔记配套出5道ArrayList编程练习题(学生类3基础+2进阶)

WanJL 7 órája
szülő
commit
d49952d41f

+ 1 - 1
README.md

@@ -70,4 +70,4 @@
 | 2026-07-24 | [多态练习](./课堂练习题/20260724-多态练习.md) | 多态概念与三前提、多态成员访问特点(编译看左运行看右)、向上转型/向下转型、instanceof运算符、多态+对象数组+排序综合(员工绩效管理系统)、接口多态+Usb设备管理器 |
 | 2026-07-24 | [多态练习](./课堂练习题/20260724-多态练习.md) | 多态概念与三前提、多态成员访问特点(编译看左运行看右)、向上转型/向下转型、instanceof运算符、多态+对象数组+排序综合(员工绩效管理系统)、接口多态+Usb设备管理器 |
 | 2026-07-27 | [内部类练习](./课堂练习题/20260727-内部类练习.md) | 成员内部类、私有内部类设计原则、静态成员内部类、局部内部类、匿名内部类三种使用方式(多态接收/方法参数/匿名对象直接调用)、匿名内部类 + 接口回调 + 排序/筛选策略模式(学生信息管理系统) |
 | 2026-07-27 | [内部类练习](./课堂练习题/20260727-内部类练习.md) | 成员内部类、私有内部类设计原则、静态成员内部类、局部内部类、匿名内部类三种使用方式(多态接收/方法参数/匿名对象直接调用)、匿名内部类 + 接口回调 + 排序/筛选策略模式(学生信息管理系统) |
 | 2026-07-28 | [异常处理练习](./课堂练习题/20260728-异常处理练习.md) | 异常概念与 Throwable 体系、try-catch 多 catch 块捕获(ArrayIndexOutOfBoundsException / NullPointerException / ClassCastException / ArithmeticException)、多 catch 块顺序、throws 抛出、程序鲁棒性、自定义异常(继承 Exception)、异常处理在业务逻辑中的应用(用户注册验证 + 银行 ATM 取款) |
 | 2026-07-28 | [异常处理练习](./课堂练习题/20260728-异常处理练习.md) | 异常概念与 Throwable 体系、try-catch 多 catch 块捕获(ArrayIndexOutOfBoundsException / NullPointerException / ClassCastException / ArithmeticException)、多 catch 块顺序、throws 抛出、程序鲁棒性、自定义异常(继承 Exception)、异常处理在业务逻辑中的应用(用户注册验证 + 银行 ATM 取款) |
-
+| 2026-07-29 | [集合框架练习](./课堂练习题/20260729-集合框架练习.md) | ArrayList 基本操作(增删改查)、ArrayList 底层原理、包装类在集合中的应用、ArrayList 嵌套二维结构、冒泡排序、contains()/indexOf() 方法 |

+ 14 - 0
授课代码/c260729/src/course/collection/Demo02.java

@@ -98,6 +98,20 @@ public class Demo02 {
 
 
                 ArrayList每次扩容的时候,都是原来容量的1.5倍。
                 ArrayList每次扩容的时候,都是原来容量的1.5倍。
 
 
+            ArrayList常用的方法:
+                创建集合对象: ArrayList list=new ArrayList<>();
+                list.add(对象);   //添加元素到集合
+                list.add(索引值,对象);//添加元素到集合的指定位置
+                list.isEmpty(); //判断集合是否为空
+                list.size();//获取集合长度
+                list.toArray();//把集合转换为数组
+                list.get(索引值);  //获取指定索引位置的元素
+                list.getFirst();//获取集合第一个元素
+                list.getLast();//获取集合最后一个元素
+                list.indexOf(对象);查询集合中这个元素首次出现的索引值,没有就返回-1
+
+
+
      */
      */
     public static void main(String[] args) {
     public static void main(String[] args) {
         ArrayList list01=new ArrayList<>(); //创建一个默认容量为10集合
         ArrayList list01=new ArrayList<>(); //创建一个默认容量为10集合

+ 41 - 0
课堂笔记/01-JavaSE基础-笔记/20260729-笔记.md

@@ -385,6 +385,45 @@ System.out.println(20 >> 1);  // 20 ÷ 2 = 10
 
 
 > 📄 来源:`collection/Demo02.java`
 > 📄 来源:`collection/Demo02.java`
 
 
+### 2.4.6 ArrayList 常用方法速查
+
+| 方法 | 说明 |
+|------|------|
+| `add(E e)` | 向集合末尾添加元素 |
+| `add(int index, E element)` | 向集合指定位置插入元素 |
+| `get(int index)` | 获取指定索引位置的元素 |
+| `getFirst()` | 获取集合第一个元素(JDK 21+) |
+| `getLast()` | 获取集合最后一个元素(JDK 21+) |
+| `set(int index, E element)` | 修改指定索引位置的元素 |
+| `remove(int index)` | 删除指定索引位置的元素 |
+| `remove(Object o)` | 删除第一个匹配的指定元素 |
+| `size()` | 获取集合中元素的个数 |
+| `isEmpty()` | 判断集合是否为空(`size == 0`) |
+| `contains(Object o)` | 判断集合是否包含指定元素 |
+| `indexOf(Object o)` | 返回指定元素首次出现的索引,不存在则返回 -1 |
+| `toArray()` | 将集合转换为 `Object[]` 数组 |
+| `clear()` | 清空集合中的所有元素 |
+
+```java
+ArrayList<String> list = new ArrayList<>();
+list.add("Java");           // 添加元素
+list.add(0, "Python");      // 在索引 0 插入
+list.get(0);                // 获取索引 0 的元素
+list.getFirst();            // 获取第一个元素
+list.getLast();             // 获取最后一个元素
+list.set(0, "C++");         // 修改索引 0 的元素
+list.remove(0);             // 删除索引 0 的元素
+list.remove("Java");        // 按元素删除
+list.size();                // 元素个数
+list.isEmpty();             // 是否为空
+list.contains("Java");      // 是否包含
+list.indexOf("Java");       // 查找索引
+Object[] arr = list.toArray(); // 转数组
+list.clear();               // 清空
+```
+
+> 📄 来源:`collection/Demo02.java`
+
 ---
 ---
 
 
 ## 三、随堂练习要点
 ## 三、随堂练习要点
@@ -401,6 +440,7 @@ System.out.println(20 >> 1);  // 20 ÷ 2 = 10
 | **ArrayList 底层原理** | **可变数组、默认容量10、扩容机制、三个构造方法、size vs capacity** | `collection/Demo02.java` |
 | **ArrayList 底层原理** | **可变数组、默认容量10、扩容机制、三个构造方法、size vs capacity** | `collection/Demo02.java` |
 | **ArrayList 扩容方法** | **trimToSize 缩减容量、ensureCapacity 手动扩容、grow 1.5倍扩容公式** | `collection/Demo02.java` |
 | **ArrayList 扩容方法** | **trimToSize 缩减容量、ensureCapacity 手动扩容、grow 1.5倍扩容公式** | `collection/Demo02.java` |
 | **位运算符** | **`>>` 右移(除2)、`<<` 左移(乘2)在扩容中的使用** | `collection/Demo02.java` |
 | **位运算符** | **`>>` 右移(除2)、`<<` 左移(乘2)在扩容中的使用** | `collection/Demo02.java` |
+| **ArrayList 常用方法** | **add/get/set/remove/size/isEmpty/contains/indexOf/toArray/getFirst/getLast** | `collection/Demo02.java` |
 
 
 ### 包装类重点
 ### 包装类重点
 
 
@@ -423,6 +463,7 @@ System.out.println(20 >> 1);  // 20 ÷ 2 = 10
    - 三个构造方法的区别
    - 三个构造方法的区别
    - `size` 与 `capacity` 的区别:`size` 是元素个数,`capacity` 是数组物理长度
    - `size` 与 `capacity` 的区别:`size` 是元素个数,`capacity` 是数组物理长度
    - 允许存储 `null`,非线程安全
    - 允许存储 `null`,非线程安全
+   - **ArrayList 常用方法**:`add()`/`get()`/`set()`/`remove()`/`size()`/`isEmpty()`/`contains()`/`indexOf()`/`toArray()`/`getFirst()`/`getLast()`
    - `trimToSize()`:缩减容量到有效元素个数
    - `trimToSize()`:缩减容量到有效元素个数
    - `ensureCapacity()`:手动提前扩容优化性能
    - `ensureCapacity()`:手动提前扩容优化性能
    - `grow()`:每次扩容为旧容量的 **1.5 倍**(`oldCapacity + oldCapacity >> 1`)
    - `grow()`:每次扩容为旧容量的 **1.5 倍**(`oldCapacity + oldCapacity >> 1`)

+ 500 - 0
课堂练习题/20260729-集合框架练习.md

@@ -0,0 +1,500 @@
+# 2026-07-29 集合框架(Collection Framework)基础练习(课堂练习用)
+
+> **说明**:以下习题围绕今日授课核心内容——**Java 集合框架入门(Collection Framework)** 展开,涵盖集合 vs 数组对比、ArrayList 基本操作(增删改查)、ArrayList 底层原理(容量/扩容/size)、包装类在集合中的应用等知识点。
+>
+> 题目分为 **基础练习**(ArrayList 基本操作,3 题)和 **进阶挑战**(综合应用,2 题)。
+
+---
+
+# 第一部分:基础练习
+
+> 以下练习围绕 ArrayList 的基本 CRUD 操作和常用方法,由浅入深。
+
+---
+
+## 练习 1:学生信息录入系统
+
+**难度**:⭐  
+**知识点**:ArrayList 创建、add() 添加元素、size() 获取个数、包装类应用
+
+**场景描述**:学校需要一个简单的学生信息录入系统,使用 ArrayList 存储学生信息,要求使用包装类 `Integer` 表示年龄。
+
+**题目要求**:
+
+**步骤 1**:创建一个 `Student` 类,包含以下属性:
+
+| 属性 | 类型 | 说明 |
+|------|------|------|
+| `name` | `String` | 姓名 |
+| `age` | `Integer` | 年龄(使用包装类) |
+| `studentId` | `String` | 学号 |
+
+要求:提供 full getter/setter 方法和无参/全参构造方法。
+
+**步骤 2**:在 `StudentManager` 类的 `main` 方法中,完成以下操作:
+
+```java
+public class StudentManager {
+    public static void main(String[] args) {
+        // 1. 创建一个 ArrayList,用于存储 Student 对象
+        //    提示:ArrayList<Student> students = new ArrayList<>();
+
+        // 2. 创建 4 个 Student 对象,信息如下:
+        //    张三, 20, S001
+        //    李四, 21, S002
+        //    王五, 19, S003
+        //    赵六, 22, S004
+
+        // 3. 将 4 个学生对象添加到 ArrayList 中
+
+        // 4. 输出 ArrayList 中的学生总数(使用 size() 方法)
+
+        // 5. 遍历 ArrayList,打印每个学生的信息(使用 for 循环 + get() 方法)
+        //    输出格式:学号:S001, 姓名:张三, 年龄:20
+    }
+}
+```
+
+**预期输出**:
+```
+学生总数:4
+========== 学生列表 ==========
+学号:S001, 姓名:张三, 年龄:20
+学号:S002, 姓名:李四, 年龄:21
+学号:S003, 姓名:王五, 年龄:19
+学号:S004, 姓名:赵六, 年龄:22
+```
+
+**提示**:
+- 创建 ArrayList 的语法:`ArrayList<Student> list = new ArrayList<>();`
+- 添加元素:`list.add(student);`
+- 获取元素个数:`list.size()`
+- 获取指定索引元素:`list.get(index)`
+
+---
+
+## 练习 2:学生信息维护——增删改查
+
+**难度**:⭐⭐  
+**知识点**:ArrayList 的 add()/remove()/set()/get()/isEmpty() 方法
+
+**场景描述**:基于练习 1 的 Student 类,实现学生信息的增删改查功能。
+
+**题目**:在 `StudentManager` 类的 `main` 方法中,基于已有学生列表,依次完成以下操作:
+
+```java
+// 假设已有练习 1 中的 students 列表(张三、李四、王五、赵六)
+
+// 1. 判断列表是否为空(使用 isEmpty()),输出结果
+
+// 2. 查询学号为 S003 的学生(遍历查找),输出其信息
+
+// 3. 修改学号为 S002 的学生姓名将"李四"改为"李思"
+
+// 4. 删除学号为 S004 的学生(赵六)
+
+// 5. 在索引 1 的位置插入一个新学生:孙七, 18, S005
+
+// 6. 再次遍历输出所有学生信息
+
+// 7. 查看此时列表中学生总数
+```
+
+**预期输出**:
+```
+列表是否为空?false
+--- 查询结果 ---
+学号:S003, 姓名:王五, 年龄:19
+已修改学号 S002 的学生姓名为:李思
+已删除学号 S004 的学生:赵六
+已在索引 1 处插入新学生:孙七
+========== 最终学生列表 ==========
+学号:S001, 姓名:张三, 年龄:20
+学号:S005, 姓名:孙七, 年龄:18
+学号:S002, 姓名:李思, 年龄:21
+学号:S003, 姓名:王五, 年龄:19
+当前学生总数:4
+```
+
+**提示**:
+- `list.isEmpty()` — 判断是否为空
+- `list.set(index, newValue)` — 修改指定位置的元素
+- `list.remove(index)` — 删除指定位置的元素
+- `list.add(index, element)` — 在指定位置插入元素
+
+---
+
+## 练习 3:学生年龄统计与分析
+
+**难度**:⭐⭐  
+**知识点**:ArrayList 遍历、条件筛选、包装类自动拆箱、统计计算
+
+**场景描述**:对学生列表进行年龄统计分析。
+
+**题目**:在 `StudentManager` 类的 `main` 方法中,对学生列表进行以下统计:
+
+```java
+// 假设已有练习 1 中的 students 列表(张三、李四、王五、赵六)
+
+// 1. 计算所有学生的平均年龄(注意:age 是 Integer 类型,参与运算时会自动拆箱)
+//    输出格式:"平均年龄:XX.X"
+
+// 2. 统计年龄 >= 20 岁的学生,输出他们的信息
+//    输出格式:
+//      年龄 >= 20 岁的学生:
+//      学号:S001, 姓名:张三, 年龄:20
+//      ...
+
+// 3. 找出年龄最大的学生,输出其信息
+//    输出格式:"年龄最大的学生:学号:S002, 姓名:李四, 年龄:21"
+
+// 4. 按年龄从小到大输出所有学生信息(冒泡排序或选择排序,基于 ArrayList)
+```
+
+**预期输出**:
+```
+========== 年龄统计 ==========
+平均年龄:20.5
+---------- 年龄 >= 20 岁 ----------
+学号:S001, 姓名:张三, 年龄:20
+学号:S002, 姓名:李四, 年龄:21
+学号:S004, 姓名:赵六, 年龄:22
+---------- 年龄最大的学生 ----------
+学号:S004, 姓名:赵六, 年龄:22
+---------- 按年龄排序(升序) ----------
+学号:S003, 姓名:王五, 年龄:19
+学号:S001, 姓名:张三, 年龄:20
+学号:S002, 姓名:李四, 年龄:21
+学号:S004, 姓名:赵六, 年龄:22
+```
+
+**思考题**:
+1. 包装类 `Integer` 参与算术运算时,底层发生了什么?(提示:自动拆箱)
+2. 如果 `Student` 的 `age` 属性为 `null`,直接参与 `age.intValue()` 或算术运算会怎样?
+
+---
+
+# 第二部分:进阶挑战
+
+> 以下练习综合运用 ArrayList、包装类、面向对象思想,模拟真实业务场景。
+
+---
+
+## 进阶 1:学生选课管理系统
+
+**难度**:⭐⭐⭐  
+**知识点**:ArrayList 综合应用、contains()/indexOf() 方法、对象比较、remove() 按对象删除
+
+**场景描述**:实现一个简单的学生选课管理系统,学生可以选择已开设的课程,也可以退选课程。
+
+**题目要求**:
+
+**步骤 1**:在 `Student` 类中新增一个属性:
+
+```java
+private ArrayList<String> courses;  // 已选课程列表
+```
+
+并提供 getter/setter 方法。在构造方法中初始化 `courses = new ArrayList<>();`
+
+**步骤 2**:在 `CourseManager` 类中实现以下功能:
+
+```java
+public class CourseManager {
+    public static void main(String[] args) {
+        // 1. 创建一个学生对象:张三, 20, S001
+
+        // 2. 为该学生添加 3 门课程:"Java基础", "数据结构", "数据库原理"
+        //    提示:student.getCourses().add("课程名");
+
+        // 3. 输出该学生的已选课程列表
+        //    输出格式:"张三的已选课程:[Java基础, 数据结构, 数据库原理]"
+
+        // 4. 判断是否已选"数据结构"(使用 contains() 方法)
+        //    输出:"是否已选数据结构?true"
+
+        // 5. 退选"数据结构"课程(使用 remove() 方法按对象删除)
+        //    输出:"已退选课程:数据结构"
+
+        // 6. 再次输出该学生的已选课程列表
+        //    输出格式:"退选后的课程:[Java基础, 数据库原理]"
+
+        // 7. 查询"Java基础"课程的索引位置(使用 indexOf() 方法)
+        //    输出:"'Java基础'的索引位置:0"
+    }
+}
+```
+
+**预期输出**:
+```
+张三的已选课程:[Java基础, 数据结构, 数据库原理]
+是否已选数据结构?true
+已退选课程:数据结构
+退选后的课程:[Java基础, 数据库原理]
+'Java基础'的索引位置:0
+```
+
+**提示**:
+- `list.contains(obj)` — 判断是否包含某个元素(依赖 `equals()` 方法)
+- `list.indexOf(obj)` — 返回元素第一次出现的索引,不存在返回 -1
+- `list.remove(Object o)` — 按对象删除(注意这里是按元素值删除,不是按索引)
+
+**思考题**:
+1. `remove("数据结构")` 和 `remove(1)` 有什么区别?参数类型不同时,调用的是哪个重载方法?
+2. `contains()` 方法判断对象是否存在的依据是什么?
+
+---
+
+## 进阶 2:教室座位管理系统
+
+**难度**:⭐⭐⭐⭐  
+**知识点**:ArrayList 作为对象属性、二维结构模拟(ArrayList 嵌套)、集合与包装类综合应用
+
+**场景描述**:一个教室有 4 排座位,每排有 5 个座位。使用 `ArrayList` 模拟教室座位分配,每个座位可以坐一个学生或为空(`null`)。
+
+**题目要求**:
+
+**步骤 1**:创建一个 `Classroom` 类:
+
+```java
+public class Classroom {
+    private String className;                   // 教室名称
+    private ArrayList<ArrayList<Student>> seats;  // 座位表(4排 x 5列)
+
+    // 构造方法:初始化教室名称,创建 4 排,每排初始化为 5 个 null 座位
+    public Classroom(String className) {
+        this.className = className;
+        this.seats = new ArrayList<>();
+        for (int i = 0; i < 4; i++) {          // 4 排
+            ArrayList<Student> row = new ArrayList<>();
+            for (int j = 0; j < 5; j++) {      // 每排 5 个座位
+                row.add(null);                 // 初始为空座位
+            }
+            seats.add(row);
+        }
+    }
+
+    // 给学生分配座位(指定排和列)
+    public boolean assignSeat(int row, int col, Student student) {
+        // 检查行列是否越界(0~3, 0~4)
+        // 检查座位是否已被占用(不为 null)
+        // 如果可用,将学生放入该座位,返回 true
+        // 否则返回 false
+    }
+
+    // 显示座位分配情况
+    public void displaySeats() {
+        // 遍历所有座位,输出格式:
+        // 第1排:[张三, 李四, 空, 王五, 空]
+        // 第2排:[空, 赵六, 空, 空, 空]
+        // ...
+    }
+
+    // 统计空座位数量
+    public int countEmptySeats() {
+        // 遍历所有座位,统计 null 的数量
+    }
+
+    // 统计某排已坐人数
+    public int countOccupiedInRow(int row) {
+        // 遍历指定排,统计非 null 的数量
+    }
+}
+```
+
+**步骤 2**:在 `Classroom` 类的 `main` 方法中,测试座位管理:
+
+```java
+public static void main(String[] args) {
+    // 1. 创建一个教室 "A101"
+    Classroom classroom = new Classroom("A101");
+
+    // 2. 分配座位:
+    //    张三 -> 第1排第1座
+    //    李四 -> 第1排第2座
+    //    王五 -> 第3排第4座
+    //    赵六 -> 第2排第3座
+
+    // 3. 显示所有座位分配情况
+
+    // 4. 尝试给已占用的座位再次分配(第1排第1座已有张三),观察返回值
+
+    // 5. 统计空座位总数
+
+    // 6. 统计第1排已坐人数
+}
+```
+
+**预期输出**:
+```
+========== A101 教室座位分配 ==========
+第1排:[张三, 李四, 空, 空, 空]
+第2排:[空, 空, 赵六, 空, 空]
+第3排:[空, 空, 空, 王五, 空]
+第4排:[空, 空, 空, 空, 空]
+第1排第1座已被占用,分配失败!
+空座位总数:17
+第1排已坐人数:2
+```
+
+**提示**:
+- `ArrayList` 嵌套:`ArrayList<ArrayList<Student>>` 模拟二维结构
+- 访问元素:`seats.get(row).get(col)`
+- 修改元素:`seats.get(row).set(col, student)`
+- `null` 表示空座位
+
+**思考题**:
+1. 用集合的嵌套模拟二维结构和用二维数组 `Student[][]` 相比,有什么优势?
+2. 如果要支持动态增加排数或每排座位数,哪种数据结构更灵活?
+
+---
+
+# 参考答案要点
+
+## 练习 1 参考
+
+```java
+// Student 类
+public class Student {
+    private String name;
+    private Integer age;
+    private String studentId;
+
+    public Student() {}
+
+    public Student(String name, Integer age, String studentId) {
+        this.name = name;
+        this.age = age;
+        this.studentId = studentId;
+    }
+
+    // getter / setter 省略
+}
+
+// StudentManager 类 main 方法关键代码
+ArrayList<Student> students = new ArrayList<>();
+
+Student s1 = new Student("张三", 20, "S001");
+Student s2 = new Student("李四", 21, "S002");
+Student s3 = new Student("王五", 19, "S003");
+Student s4 = new Student("赵六", 22, "S004");
+
+students.add(s1);
+students.add(s2);
+students.add(s3);
+students.add(s4);
+
+System.out.println("学生总数:" + students.size());
+
+for (int i = 0; i < students.size(); i++) {
+    Student s = students.get(i);
+    System.out.println("学号:" + s.getStudentId()
+        + ", 姓名:" + s.getName()
+        + ", 年龄:" + s.getAge());
+}
+```
+
+## 练习 2 参考
+
+```java
+// isEmpty() 判断
+System.out.println("列表是否为空?" + students.isEmpty());
+
+// 查询学号为 S003 的学生
+for (int i = 0; i < students.size(); i++) {
+    Student s = students.get(i);
+    if ("S003".equals(s.getStudentId())) {
+        System.out.println("学号:" + s.getStudentId()
+            + ", 姓名:" + s.getName()
+            + ", 年龄:" + s.getAge());
+        break;
+    }
+}
+
+// 修改:将"李四"改为"李思"
+for (int i = 0; i < students.size(); i++) {
+    Student s = students.get(i);
+    if ("S002".equals(s.getStudentId())) {
+        s.setName("李思");
+        break;
+    }
+}
+
+// 删除赵六
+students.remove(3);
+
+// 在索引 1 处插入新学生
+students.add(1, new Student("孙七", 18, "S005"));
+```
+
+## 练习 3 参考(排序部分)
+
+```java
+// 冒泡排序(按年龄升序)
+for (int i = 0; i < students.size() - 1; i++) {
+    for (int j = 0; j < students.size() - 1 - i; j++) {
+        Student s1 = students.get(j);
+        Student s2 = students.get(j + 1);
+        if (s1.getAge() > s2.getAge()) {
+            // 交换
+            Student temp = students.get(j);
+            students.set(j, students.get(j + 1));
+            students.set(j + 1, temp);
+        }
+    }
+}
+```
+
+## 进阶 1 参考(退选课程)
+
+```java
+// 判断是否已选
+System.out.println("是否已选数据结构?"
+    + student.getCourses().contains("数据结构"));
+
+// 退选课程
+student.getCourses().remove("数据结构");
+
+// 查询索引
+System.out.println("'Java基础'的索引位置:"
+    + student.getCourses().indexOf("Java基础"));
+```
+
+## 进阶 2 参考(assignSeat 方法)
+
+```java
+public boolean assignSeat(int row, int col, Student student) {
+    // 越界检查
+    if (row < 0 || row >= seats.size()
+        || col < 0 || col >= seats.get(0).size()) {
+        System.out.println("座位位置越界!");
+        return false;
+    }
+    // 检查是否已被占用
+    if (seats.get(row).get(col) != null) {
+        System.out.println("第" + (row + 1) + "排第" + (col + 1)
+            + "座已被占用,分配失败!");
+        return false;
+    }
+    // 分配座位
+    seats.get(row).set(col, student);
+    return true;
+}
+```
+
+---
+
+# 涵盖知识点总览
+
+| 知识点 | 对应练习 | 说明 |
+|--------|---------|------|
+| ArrayList 创建与元素添加 | 练习 1 | `new ArrayList<>()`, `add()` |
+| ArrayList 遍历 | 练习 1、2、3 | `for` + `get()`, `size()` |
+| ArrayList 修改与删除 | 练习 2 | `set()`, `remove(index)` |
+| ArrayList 插入 | 练习 2 | `add(index, element)` |
+| ArrayList 查询与判断 | 进阶 1 | `contains()`, `indexOf()` |
+| 包装类自动拆箱 | 练习 3 | `Integer` 参与算术运算 |
+| 条件筛选与统计 | 练习 3 | 遍历 + 条件判断 |
+| 对象排序(冒泡排序) | 练习 3 | ArrayList 中的元素交换 |
+| ArrayList 嵌套(二维结构) | 进阶 2 | `ArrayList<ArrayList<Student>>` |
+| null 在集合中的语义 | 进阶 2 | `null` 表示空座位 |