下午 2.5h
3. Map 集合入门 & HashMap 核心
3.1 核心概念
- Map 是双列集合 :存储
键值对(Key-Value) - Key:唯一、不可重复;Value:可重复
- HashMap:开发最常用,底层哈希表,线程不安全,效率高
- 键和值都可以为
null(但键只能有一个 null)
3.2 计划遗漏重要知识点
- Hashtable:线程安全、效率低、不允许 null 键 null 值(老版本用)
- TreeMap:可对键自动排序
4. HashMap 四大核心方法(必默写)
4.1 方法详解
put(K key, V value):添加 / 覆盖- key 不存在 → 添加
- key 已存在 → 用新 value 覆盖旧 value
get(K key):根据 key 获取 value,key 不存在返回 nullremove(K key):根据 key 删除整个键值对containsKey(key):判断是否包含指定键containsValue(value):判断是否包含指定值
4.2 完整实战代码(学号 - 学生对象)
java
运行
import java.util.HashMap;
public class HashMapMethodDemo {
public static void main(String[] args) {
// 1. 创建HashMap:键=学号(String),值=学生对象
HashMap<String, Student> map = new HashMap<>();
// 2. put 添加元素
map.put("001", new Student("001", "张三"));
map.put("002", new Student("002", "李四"));
map.put("001", new Student("001", "张三三")); // 键重复 → 覆盖
// 3. get 根据键取值
Student s = map.get("002");
System.out.println("学号002的学生:" + s);
// 4. containsKey 判断键是否存在
System.out.println("是否包含003:" + map.containsKey("003"));
// 5. remove 根据键删除
map.remove("001");
System.out.println("删除后集合:" + map);
}
}
晚上 1.5h
5. HashMap 两种基础遍历
5.1 遍历方式 1:遍历所有 key(最常用)
步骤:keySet() → 得到所有键的集合 → 遍历键 → get() 取值
java
运行
System.out.println("-----遍历key-----");
Set<String> keys = map.keySet();
for (String key : keys) {
Student value = map.get(key);
System.out.println("键:" + key + ",值:" + value);
}
5.2 遍历方式 2:直接遍历所有 value
步骤:values() → 得到所有值的集合
java
运行
System.out.println("-----遍历value-----");
Collection<Student> values = map.values();
for (Student value : values) {
System.out.println(value);
}
计划遗漏补充(高频面试)
HashMap 第三种遍历:entrySet ()(企业开发首选)
java
运行
// 键值对一起遍历,效率最高
Set<Map.Entry<String, Student>> entries = map.entrySet();
for (Map.Entry<String, Student> entry : entries) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
Day22 过关标准(自测)
- 能口述 HashSet 去重完整流程
- 能给自定义对象实现去重
- 能默写 HashMap 增删查改方法
- 会写 key、value、entrySet 三种遍历
- 能完成:学号 - 学生、姓名 - 分数的增删改查
上午 3h
1. 泛型深度进阶
1.1 泛型作用(必须理解)
- 类型约束:限定集合存储的数据类型
- 避免强制类型转换
- 编译期安全:编译时报错,而非运行时报错
1.2 泛型分类
- 泛型类 :
class 类名<T> - 泛型方法 :
public <T> 返回值 方法名(T t) - 通配符
?:表示任意类型 - 受限泛型
? extends 类:上限,只能是该类或其子类? super 类:下限,只能是该类或其父类
1.3 泛型类 完整代码
java
运行
// T:泛型标识,代表任意引用类型
public class GenericClass<T> {
private T data;
public GenericClass(T data) {
this.data = data;
}
public T getData() {
return data;
}
}
// 测试
public class Test {
public static void main(String[] args) {
// 存储字符串
GenericClass<String> g1 = new GenericClass<>("Java");
// 存储整数
GenericClass<Integer> g2 = new GenericClass<>(100);
}
}
1.4 泛型方法 完整代码
java
运行
public class GenericMethod {
// 泛型方法:打印任意类型数组
public static <T> void printArray(T[] arr) {
for (T t : arr) {
System.out.print(t + " ");
}
System.out.println();
}
public static void main(String[] args) {
Integer[] arr1 = {1,2,3};
String[] arr2 = {"A","B","C"};
printArray(arr1); // 1 2 3
printArray(arr2); // A B C
}
}
这一部分的解释
逐行运行逻辑(从上到下执行)
-
程序入口 Java 运行自动找
main方法,从main里面第一行开始执行。 -
执行代码①
java
运行
GenericClass<String> g1 = new GenericClass<>("Java");
- 声明泛型类型:
<String> - 调用构造方法 ,传入参数:
"Java" - 进入构造方法:
this.data = data;→ 把传入的Java赋值给成员变量private T data - 此时:
g1对象内部的 data = 字符串Java
- 执行代码②
java
运行
GenericClass<Integer> g2 = new GenericClass<>(100);
- 声明泛型类型:
<Integer> - 调用构造方法,传入参数:
100 - 给成员变量 data 赋值:
data = 100 - 此时:
g2对象内部的 data = 整数100
- 执行打印
java
运行
g1.getData()
- 调用
getData()方法 - 方法内部
return data - 取出 g1 存的
Java→ 打印输出
java
运行
g2.getData()
- 取出 g2 存的
100→ 打印输出
三、泛型 <T> 核心运行规则
- 你写
GenericClass<String>👉 整个类里所有 T 全部替换成 String - 你写
GenericClass<Integer>👉 整个类里所有 T 全部替换成 Integer
等价理解
- g1 生效时:
java
运行
private String data;
public GenericClass(String data){}
public String getData(){}
- g2 生效时:
java
运行
private Integer data;
public GenericClass(Integer data){}
public Integer getData(){}
四、一句话总结整体逻辑
- 创建对象时,指定泛型类型
- 构造方法接收数据,存入成员变量
- 调用
getData()取出保存的数据 - 控制台打印输出
1.5 通配符?完整代码
java
运行
// 接收任意泛型集合
public static void printList(List<?> list) {
for (Object o : list) {
System.out.println(o);
}
}
2. 泛型代码实操(已包含在上面,直接运行)
下午 2.5h
3. Collections 工具类(集合专用)
3.1 重要区分
- Collection:List/Set 的根接口
- Collections :操作集合的工具类,全是静态方法
3.2 核心静态方法(完整代码)
java
运行
import java.util.ArrayList;
import java.util.Collections;
public class CollectionsDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
// 1. 批量添加
Collections.addAll(list, 5,3,8,1);
// 2. 升序排序
Collections.sort(list);
// 3. 打乱顺序
Collections.shuffle(list);
// 4. 最大值、最小值
System.out.println(Collections.max(list));
System.out.println(Collections.min(list));
// 5. 反转
Collections.reverse(list);
}
}
计划遗漏补充
- 空集合 :
Collections.emptyList()(不存储元素,节省内存) - 不可变集合 :
List.of()、Map.of()(JDK9+,不能增删改)
晚上 1.5h
4. 综合大练习:集合版学生管理系统
功能清单
- 添加学生
- 删除学生(按学号)
- 修改学生信息
- 查询单个学生
- 查询所有学生
- 按学号 / 成绩排序
- 泛型 + HashMap/ArrayList 实现
完整可运行代码(直接复制使用)
java
运行
import java.util.*;
// 学生类
class Student {
private String id;
private String name;
private int score;
public Student(String id, String name, int score) {
this.id = id;
this.name = name;
this.score = score;
}
// getter、setter、toString
public String getId() {return id;}
public String getName() {return name;}
public int getScore() {return score;}
public void setName(String name) {this.name = name;}
public void setScore(int score) {this.score = score;}
@Override
public String toString() {
return "学号:"+id+",姓名:"+name+",分数:"+score;
}
}
// 学生管理系统
public class StudentManager {
// 用HashMap存储:key=学号,value=学生
private static HashMap<String, Student> stuMap = new HashMap<>();
private static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
while (true) {
System.out.println("=====学生管理系统=====");
System.out.println("1.添加 2.删除 3.修改 4.查询 5.全部展示 6.排序 0.退出");
int choice = sc.nextInt();
switch (choice) {
case 1: addStu(); break;
case 2: deleteStu(); break;
case 3: updateStu(); break;
case 4: findStu(); break;
case 5: showAll(); break;
case 6: sortStu(); break;
case 0: return;
}
}
}
// 添加
private static void addStu() {
System.out.print("输入学号:");
String id = sc.next();
if (stuMap.containsKey(id)) {
System.out.println("学号已存在!");
return;
}
System.out.print("输入姓名:");
String name = sc.next();
System.out.print("输入分数:");
int score = sc.nextInt();
stuMap.put(id, new Student(id, name, score));
System.out.println("添加成功");
}
// 删除
private static void deleteStu() {
System.out.print("输入要删除的学号:");
String id = sc.next();
if (stuMap.remove(id) != null) System.out.println("删除成功");
else System.out.println("学号不存在");
}
// 修改
private static void updateStu() {
System.out.print("输入要修改的学号:");
String id = sc.next();
Student s = stuMap.get(id);
if (s == null) {
System.out.println("学号不存在");
return;
}
System.out.print("输入新姓名:");
s.setName(sc.next());
System.out.print("输入新分数:");
s.setScore(sc.nextInt());
System.out.println("修改成功");
}
// 查询单个
private static void findStu() {
System.out.print("输入学号:");
Student s = stuMap.get(sc.next());
System.out.println(s == null ? "无此学生" : s);
}
// 展示全部
private static void showAll() {
for (Student s : stuMap.values()) System.out.println(s);
}
// 排序(Collections.sort)
private static void sortStu() {
ArrayList<Student> list = new ArrayList<>(stuMap.values());
// 按分数升序
Collections.sort(list, Comparator.comparingInt(Student::getScore));
for (Student s : list) System.out.println(s);
}
}
Day22 过关标准(自测)
- 能区分泛型类、泛型方法、通配符
? - 能独立使用 Collections 排序、打乱、批量添加
- 能独立写出学生管理系统
- 能使用 HashMap + ArrayList 完成增删改查
- 能使用泛型保证类型安全
今日重点理解
Student s = stuMap.get(id);
stuMap.put(id, new Student(id, name, score));这两句
先看整行
java
运行
Student s = stuMap.get(id);
1. 逐个单词翻译
Student:学生类型(引用类型)s:自定义变量名,用来接收学生对象stuMap:你创建的 HashMap 集合.get(键):Map 专属方法作用:根据【key 键】,取出对应的【value 值】id:你键盘输入的学号(就是 Map 里的 key)
2. 整句话完整意思
java
运行
// 根据输入的学号id,去map集合里找对应的学生
// 找到就把学生对象 赋值给变量 s
Student s = stuMap.get(id);
大白话:拿着学号,去集合里查这个人,查到就把这个人拿出来交给 s
3. 结合你项目的数据结构
你的 map:
java
运行
HashMap<String, Student> stuMap
key(键) = 学号 String
value(值) = 学生对象 Student
存入时:
java
运行
stuMap.put(学号, 学生对象);
取出时:
java
运行
stuMap.get(学号) 👉 返回 对应的学生对象
4. 两种结果(重点必考)
-
如果集合里有这个学号
s= 真实的学生对象后面可以:s.setName()、s.getScore()正常使用 -
如果没有这个学号
s = null代表:空、没找到这个人
所以代码里会判断:
java
运行
if(s == null){
System.out.println("学号不存在");
}
5. 超短背诵版
map.get(键)→ 通过键拿值- 这里键是学号,值是学生
- 查到返回学生对象,查不到返回 null
Student s用来接收取出来的学生
stuMap.put(id, new Student(id, name, score))
原代码
java
运行
stuMap.put(id, new Student(id, name, score));
第一步:先认识每个东西
stuMap你定义的:
java
运行
HashMap<String,Student> stuMap
作用:存「学号 → 学生对象」
-
.put(键,值)Map 固定方法 作用:往集合里添加一组 键值对数据 -
第一个参数
id就是你键盘输入的学号 ,作为 Map 的 key (键) -
第二个参数
new Student(id, name, score)
new Student():新建一个学生对象- 括号里三个参数:把输入的 学号、姓名、分数,传给学生构造方法直接创建出一个完整学生
第二步:整句拆开
java
运行
// 左边键:id(学号)
// 右边值:new出来的学生对象
stuMap.put( 键 , 值 );
完整翻译:
拿着输入的学号当做 key新建一个学生对象当做 value把这一对数据,存入 stuMap 集合
第三步:拆成两行等价写法(更好理解)
java
运行
// 1. 先创建学生对象
Student oneStu = new Student(id, name, score);
// 2. 再存入map
stuMap.put(id, oneStu);
你原来那一行,只是合并写成一行,效果完全一样。
第四步:运行流程(一步不落)
- 你输入学号
id - 你输入姓名
name - 你输入分数
score - 执行这句:
- 自动
new一个学生,打包好三个数据 - 以学号为钥匙,把这个学生放进 HashMap
- 自动
- 存完,系统里就有这个学生了
第五步:必考核心
put= 新增 / 覆盖- key(学号)唯一
- 如果学号重复执行 put,会覆盖旧学生数据所以代码前面会先判断:
java
运行
if(stuMap.containsKey(id)){
学号已存在,不让添加
}
大白话终极总结
java
运行
stuMap.put(id, new Student(id, name, score));
👉 新建一个学生,用学号当钥匙,存进集合里。