|
|
@@ -6,12 +6,51 @@
|
|
|
|
|
|
---
|
|
|
|
|
|
+## 📌 本次作业重要说明
|
|
|
+
|
|
|
+### 命名要求
|
|
|
+
|
|
|
+| 项目 | 要求 |
|
|
|
+|------|------|
|
|
|
+| **包名** | **必须按题目指定的包名创建**(全小写) |
|
|
|
+| **类名** | 自由命名,但需**见名知意** |
|
|
|
+| **测试类** | 建议命名为 `TestXxx` 或 `XxxTest` |
|
|
|
+| **文件名** | 必须与类名一致 |
|
|
|
+
|
|
|
+### 提交目录结构示例
|
|
|
+
|
|
|
+```
|
|
|
+提交\
|
|
|
+└─ 张三\
|
|
|
+ ├─ p1_list\ ← 第 1 题的包(ArrayList / LinkedList)
|
|
|
+ │ └─ ListDemo.java
|
|
|
+ ├─ p2_map\ ← 第 2 题的包(HashMap / TreeMap)
|
|
|
+ │ └─ MapDemo.java
|
|
|
+ ├─ p3_set\ ← 第 3 题的包(HashSet / TreeSet)
|
|
|
+ │ └─ SetDemo.java
|
|
|
+ ├─ p4_exception\ ← 第 4 题的包(异常 + 集合)
|
|
|
+ │ ├─ InvalidScoreException.java
|
|
|
+ │ └─ ScoreStatisticsDemo.java
|
|
|
+ └─ p5_sort\ ← 第 5 题的包(匿名内部类 + 排序)
|
|
|
+ ├─ Student.java
|
|
|
+ └─ SortDemo.java
|
|
|
+```
|
|
|
+
|
|
|
+> ⚠ **注意**:
|
|
|
+> 1. 包名必须严格按题目要求书写(全小写),目录结构必须与包结构一致
|
|
|
+> 2. 每个 Java 文件头部需包含 `@author`、`@title`、`@create` 文档注释
|
|
|
+> 3. 简答题(HashMap 底层原理)请写在 Word / TXT 文档中,与代码一起提交
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
# 第一部分:基础题(⭐ 必做)
|
|
|
|
|
|
---
|
|
|
|
|
|
## 作业 1:ArrayList 与 LinkedList 基本操作 — 学生名单管理
|
|
|
|
|
|
+**包名**:`p1_list`
|
|
|
+
|
|
|
**知识点**:`ArrayList` / `LinkedList` 创建、增删改查、三种遍历方式(`for+get` / `Iterator` 迭代器 / 增强 for)
|
|
|
|
|
|
**场景描述**:使用 ArrayList 和 LinkedList 分别存储学生名单,练习集合的**增删改查**与**三种遍历方式**,体会 List 系集合的通用操作。
|
|
|
@@ -72,6 +111,8 @@ LinkedList 大小:5
|
|
|
|
|
|
## 作业 2:HashMap 与 TreeMap 基本操作 — 学生成绩表
|
|
|
|
|
|
+**包名**:`p2_map`
|
|
|
+
|
|
|
**知识点**:`HashMap` / `TreeMap` 创建、`put()` / `get()` / `containsKey()` / `remove()` / `keySet()` / `entrySet()`、Map 两种遍历方式
|
|
|
|
|
|
**场景描述**:用 Map 存储学生成绩(学号 → 成绩)。**HashMap 无序**,**TreeMap 按键自动排序**——对比两者遍历顺序的差异。
|
|
|
@@ -142,6 +183,8 @@ public class MapDemo {
|
|
|
|
|
|
## 作业 3:HashSet 与 TreeSet 基本操作 — 单词去重与排序
|
|
|
|
|
|
+**包名**:`p3_set`
|
|
|
+
|
|
|
**知识点**:`HashSet` 去重、`TreeSet` 自动排序、迭代器 / 增强 for 遍历
|
|
|
|
|
|
**场景描述**:Set 集合**无序、不可重复**。HashSet 去重(无序),TreeSet 自动排序(有序)。模拟水果清单去重与数字排序。
|
|
|
@@ -197,6 +240,8 @@ public class SetDemo {
|
|
|
|
|
|
## 作业 4:异常处理 + 集合综合 — 学生成绩统计系统
|
|
|
|
|
|
+**包名**:`p4_exception`
|
|
|
+
|
|
|
**知识点**:`try-catch` 多 catch 块、自定义异常、异常处理 + ArrayList 综合应用、迭代器遍历
|
|
|
|
|
|
**场景描述**:编写成绩统计程序,把输入的成绩存入 `ArrayList`,计算总分和平均分。要求处理三类异常:**输入不是整数**(`InputMismatchException`)、**成绩不合法**(自定义异常 `InvalidScoreException`)、**索引越界**(`IndexOutOfBoundsException`)。
|
|
|
@@ -264,6 +309,7 @@ public class ScoreStatisticsDemo {
|
|
|
- 可以结合 `while` 循环实现"输入错误就重试"的鲁棒性
|
|
|
|
|
|
**思考题**(选做,不要求提交代码):
|
|
|
+
|
|
|
1. 多 catch 块的书写顺序有什么要求?为什么子类必须在前?
|
|
|
2. 自定义异常继承 `Exception`(编译期)和 `RuntimeException`(运行期)有什么区别?
|
|
|
3. 为什么输入不是整数后要调用 `nextLine()` 清空缓冲?
|
|
|
@@ -272,6 +318,8 @@ public class ScoreStatisticsDemo {
|
|
|
|
|
|
## 作业 5:匿名内部类 + 集合排序 — 学生排序系统
|
|
|
|
|
|
+**包名**:`p5_sort`
|
|
|
+
|
|
|
**知识点**:**匿名内部类**实现 `Comparator`、`Collections.sort()`、`TreeSet` 自定义排序、List / Set 排序
|
|
|
|
|
|
**场景描述**:定义 `Student` 类(name + age + score),用**匿名内部类**实现 `Comparator` 接口,对集合中的学生按年龄、成绩、姓名排序。体会匿名内部类"临时定义一个实现类"的便捷性。
|
|
|
@@ -375,291 +423,3 @@ Student{name='赵六', age=21, score=88.0}
|
|
|
- 哈希冲突:多个键的哈希值相同 → 挂到同一位置的链表上(链地址法)
|
|
|
- 树化条件:**链表节点长度 > 8 且 数组长度 > 64**(两个条件同时满足);退化条件:**节点长度 < 6**
|
|
|
- 默认容量 **16**,负载因子 **0.75f**:已存元素超过容量 × 0.75 时触发扩容
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-# 提交要求
|
|
|
-
|
|
|
-1. 新建 Java 项目(或使用现有项目),包名建议:`homework0731`
|
|
|
-2. 完成作业 1~5 的编程题,每个类文件头部包含 `@author`、`@title`、`@create` 文档注释
|
|
|
-3. 简答题写在 Word / TXT 文档中(或写在代码注释里)
|
|
|
-4. 运行代码,控制台输出需与预期输出一致
|
|
|
-5. **将代码源文件和运行结果截图**提交到班级群
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-# 参考答案(供批改参考)
|
|
|
-
|
|
|
-## 作业 1 参考
|
|
|
-
|
|
|
-```java
|
|
|
-import java.util.*;
|
|
|
-
|
|
|
-public class ListDemo {
|
|
|
- public static void main(String[] args) {
|
|
|
- ArrayList<String> arrayList = new ArrayList<>();
|
|
|
- LinkedList<String> linkedList = new LinkedList<>();
|
|
|
- String[] names = {"张三", "李四", "王五", "赵六", "孙七"};
|
|
|
- for (String name : names) {
|
|
|
- arrayList.add(name);
|
|
|
- linkedList.add(name);
|
|
|
- }
|
|
|
-
|
|
|
- System.out.println("ArrayList 大小:" + arrayList.size());
|
|
|
- System.out.println("LinkedList 大小:" + linkedList.size());
|
|
|
- System.out.println("索引 2 的学生:" + arrayList.get(2));
|
|
|
-
|
|
|
- arrayList.set(1, "李思");
|
|
|
- System.out.println("已修改索引 1:李四 → 李思");
|
|
|
- System.out.println("已删除索引 3:" + arrayList.remove(3));
|
|
|
-
|
|
|
- System.out.println("========== 方式①:for + get ==========");
|
|
|
- for (int i = 0; i < arrayList.size(); i++) {
|
|
|
- System.out.print(arrayList.get(i) + " ");
|
|
|
- }
|
|
|
- System.out.println();
|
|
|
-
|
|
|
- System.out.println("========== 方式②:Iterator 迭代器 ==========");
|
|
|
- Iterator<String> iterator = arrayList.iterator();
|
|
|
- while (iterator.hasNext()) {
|
|
|
- System.out.print(iterator.next() + " ");
|
|
|
- }
|
|
|
- System.out.println();
|
|
|
-
|
|
|
- System.out.println("========== 方式③:增强 for ==========");
|
|
|
- for (String name : arrayList) {
|
|
|
- System.out.print(name + " ");
|
|
|
- }
|
|
|
- System.out.println();
|
|
|
-
|
|
|
- System.out.println("========== LinkedList 迭代器遍历 ==========");
|
|
|
- Iterator<String> iterator1 = linkedList.iterator();
|
|
|
- while (iterator1.hasNext()) {
|
|
|
- System.out.print(iterator1.next() + " ");
|
|
|
- }
|
|
|
- System.out.println();
|
|
|
- }
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-## 作业 2 参考
|
|
|
-
|
|
|
-```java
|
|
|
-import java.util.*;
|
|
|
-
|
|
|
-public class MapDemo {
|
|
|
- public static void main(String[] args) {
|
|
|
- HashMap<String, Integer> map = new HashMap<>();
|
|
|
- map.put("x001", 90);
|
|
|
- map.put("x002", 85);
|
|
|
- map.put("x003", 92);
|
|
|
- map.put("x004", 78);
|
|
|
-
|
|
|
- System.out.println("学生人数:" + map.size());
|
|
|
- System.out.println("学号 x002 的成绩:" + map.get("x002"));
|
|
|
- System.out.println("包含键 x001:" + map.containsKey("x001"));
|
|
|
- System.out.println("包含键 x999:" + map.containsKey("x999"));
|
|
|
-
|
|
|
- map.put("x004", 88); // 键已存在 → 覆盖旧值
|
|
|
- System.out.println("修改后 x004 的成绩:" + map.get("x004"));
|
|
|
- map.remove("x001");
|
|
|
- System.out.println("删除 x001 后,学生人数:" + map.size());
|
|
|
-
|
|
|
- System.out.println("========== HashMap 方式一:keySet + get ==========");
|
|
|
- Set<String> keys = map.keySet();
|
|
|
- for (String key : keys) {
|
|
|
- System.out.println("学号:" + key + ",成绩:" + map.get(key));
|
|
|
- }
|
|
|
-
|
|
|
- System.out.println("========== HashMap 方式二:entrySet ==========");
|
|
|
- Set<Map.Entry<String, Integer>> entries = map.entrySet();
|
|
|
- for (Map.Entry<String, Integer> me : entries) {
|
|
|
- System.out.println("学号:" + me.getKey() + ",成绩:" + me.getValue());
|
|
|
- }
|
|
|
-
|
|
|
- System.out.println("========== TreeMap keySet 遍历(按键排序) ==========");
|
|
|
- TreeMap<String, Integer> treeMap = new TreeMap<>();
|
|
|
- treeMap.put("x001", 90);
|
|
|
- treeMap.put("x002", 85);
|
|
|
- treeMap.put("x003", 92);
|
|
|
- treeMap.put("x004", 78);
|
|
|
- for (String key : treeMap.keySet()) {
|
|
|
- System.out.println("学号:" + key + ",成绩:" + treeMap.get(key));
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-## 作业 3 参考
|
|
|
-
|
|
|
-```java
|
|
|
-import java.util.*;
|
|
|
-
|
|
|
-public class SetDemo {
|
|
|
- public static void main(String[] args) {
|
|
|
- System.out.println("========== HashSet 去重 ==========");
|
|
|
- HashSet<String> hashSet = new HashSet<>();
|
|
|
- hashSet.add("香蕉");
|
|
|
- hashSet.add("苹果");
|
|
|
- hashSet.add("葡萄");
|
|
|
- hashSet.add("苹果");
|
|
|
- hashSet.add("西瓜");
|
|
|
- hashSet.add("香蕉");
|
|
|
- System.out.println("集合大小:" + hashSet.size());
|
|
|
-
|
|
|
- System.out.print("迭代器遍历:");
|
|
|
- Iterator<String> iterator = hashSet.iterator();
|
|
|
- while (iterator.hasNext()) {
|
|
|
- System.out.print(iterator.next() + " ");
|
|
|
- }
|
|
|
- System.out.println();
|
|
|
-
|
|
|
- System.out.println("========== TreeSet<String> 字典序排序 ==========");
|
|
|
- TreeSet<String> treeSet = new TreeSet<>();
|
|
|
- treeSet.add("香蕉");
|
|
|
- treeSet.add("苹果");
|
|
|
- treeSet.add("葡萄");
|
|
|
- treeSet.add("西瓜");
|
|
|
- for (String fruit : treeSet) {
|
|
|
- System.out.print(fruit + " ");
|
|
|
- }
|
|
|
- System.out.println();
|
|
|
-
|
|
|
- System.out.println("========== TreeSet<Integer> 数值升序 ==========");
|
|
|
- TreeSet<Integer> numSet = new TreeSet<>();
|
|
|
- numSet.add(50);
|
|
|
- numSet.add(20);
|
|
|
- numSet.add(80);
|
|
|
- numSet.add(10);
|
|
|
- numSet.add(60);
|
|
|
- for (Integer num : numSet) {
|
|
|
- System.out.print(num + " ");
|
|
|
- }
|
|
|
- System.out.println();
|
|
|
- }
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-## 作业 4 参考
|
|
|
-
|
|
|
-```java
|
|
|
-// InvalidScoreException.java
|
|
|
-public class InvalidScoreException extends RuntimeException {
|
|
|
- public InvalidScoreException(String message) {
|
|
|
- super(message);
|
|
|
- }
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-```java
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.InputMismatchException;
|
|
|
-import java.util.Iterator;
|
|
|
-import java.util.Scanner;
|
|
|
-
|
|
|
-public class ScoreStatisticsDemo {
|
|
|
- public static void main(String[] args) {
|
|
|
- Scanner sc = new Scanner(System.in);
|
|
|
- ArrayList<Integer> scores = new ArrayList<>();
|
|
|
-
|
|
|
- for (int i = 0; i < 5; i++) {
|
|
|
- while (true) {
|
|
|
- try {
|
|
|
- System.out.print("请输入第 " + (i + 1) + " 个成绩(0~100):");
|
|
|
- int s = sc.nextInt();
|
|
|
- if (s < 0 || s > 100) {
|
|
|
- throw new InvalidScoreException("成绩必须在0~100之间");
|
|
|
- }
|
|
|
- scores.add(s);
|
|
|
- break;
|
|
|
- } catch (InputMismatchException e) {
|
|
|
- System.out.println("输入错误,请输入整数!");
|
|
|
- sc.nextLine(); // 清空输入缓冲,防止死循环
|
|
|
- } catch (InvalidScoreException e) {
|
|
|
- System.out.println("成绩不合法:" + e.getMessage());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- System.out.println("========== 成绩统计结果 ==========");
|
|
|
- int total = 0;
|
|
|
- Iterator<Integer> iterator = scores.iterator();
|
|
|
- System.out.print("成绩列表:");
|
|
|
- while (iterator.hasNext()) {
|
|
|
- int s = iterator.next();
|
|
|
- System.out.print(s + " ");
|
|
|
- total += s;
|
|
|
- }
|
|
|
- System.out.println();
|
|
|
- System.out.println("总分:" + total + ",平均分:" + (total * 1.0 / scores.size()));
|
|
|
- }
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-## 作业 5 参考
|
|
|
-
|
|
|
-```java
|
|
|
-import java.util.*;
|
|
|
-
|
|
|
-public class SortDemo {
|
|
|
- public static void main(String[] args) {
|
|
|
- ArrayList<Student> list = new ArrayList<>();
|
|
|
- list.add(new Student("张三", 20, 85));
|
|
|
- list.add(new Student("李四", 22, 90));
|
|
|
- list.add(new Student("王五", 19, 78));
|
|
|
- list.add(new Student("赵六", 21, 88));
|
|
|
-
|
|
|
- // 按年龄升序(匿名内部类)
|
|
|
- Collections.sort(list, new Comparator<Student>() {
|
|
|
- @Override
|
|
|
- public int compare(Student s1, Student s2) {
|
|
|
- return s1.getAge() - s2.getAge();
|
|
|
- }
|
|
|
- });
|
|
|
- System.out.println("========== 按年龄升序排序 ==========");
|
|
|
- for (Student s : list) {
|
|
|
- System.out.println(s);
|
|
|
- }
|
|
|
-
|
|
|
- // 按成绩降序(匿名内部类)
|
|
|
- Collections.sort(list, new Comparator<Student>() {
|
|
|
- @Override
|
|
|
- public int compare(Student s1, Student s2) {
|
|
|
- return Double.compare(s2.getScore(), s1.getScore());
|
|
|
- }
|
|
|
- });
|
|
|
- System.out.println("========== 按成绩降序排序 ==========");
|
|
|
- for (Student s : list) {
|
|
|
- System.out.println(s);
|
|
|
- }
|
|
|
-
|
|
|
- // TreeSet 按姓名排序(匿名内部类 Comparator)
|
|
|
- TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
|
|
|
- @Override
|
|
|
- public int compare(Student s1, Student s2) {
|
|
|
- return s1.getName().compareTo(s2.getName());
|
|
|
- }
|
|
|
- });
|
|
|
- treeSet.add(new Student("张三", 20, 85));
|
|
|
- treeSet.add(new Student("李四", 22, 90));
|
|
|
- treeSet.add(new Student("王五", 19, 78));
|
|
|
- treeSet.add(new Student("赵六", 21, 88));
|
|
|
- System.out.println("========== TreeSet 按姓名排序 ==========");
|
|
|
- Iterator<Student> iterator = treeSet.iterator();
|
|
|
- while (iterator.hasNext()) {
|
|
|
- System.out.println(iterator.next());
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-## 简答题参考要点
|
|
|
-
|
|
|
-**HashMap 的底层原理**:
|
|
|
-
|
|
|
-1. **数据结构**:HashMap 底层是**哈希表**,本质是「**数组 + 链表**」;JDK 1.8 之后引入了红黑树,在满足条件时链表会**树化**为「数组 + 红黑树」。
|
|
|
-2. **键唯一性**:HashMap 依赖 `hashCode()` 和 `equals()` 保证键唯一。先调用 `hashCode()` 计算哈希值、定位数组下标;若该位置已有元素,再调用 `equals()` 比较——相同则视为同一个键(覆盖),不同则挂在链表上。
|
|
|
-3. **哈希冲突**:多个不同键计算出相同哈希值(下标)时发生冲突,HashMap 采用**链地址法**解决——冲突的元素以链表形式挂在同一数组位置上。
|
|
|
-4. **树化/退化条件**:链表节点长度 **> 8**(`TREEIFY_THRESHOLD`)且数组长度 **> 64**(`MIN_TREEIFY_CAPACITY`)两个条件**同时满足**时,链表转为红黑树;节点长度 **< 6**(`UNTREEIFY_THRESHOLD`)时退化回链表。
|
|
|
-5. **默认容量与负载因子**:默认初始容量 **16**(`1 << 4`),负载因子 **0.75f**。当已存储元素个数超过「容量 × 负载因子」(16 × 0.75 = 12)时触发扩容,扩容后容量约为原来的 2 倍。
|
|
|
-
|