Java 集合框架 Map 接口與 HashMap 完整實戰指南
Map 核心特徵
- 鍵值對 (
key-value) 存儲、key 唯一、value 可重複
- 每個 key 映射單一 value、一個 value 可對應多個 key
- 支援泛型:
Map<K, V>
- 三大視圖:
keySet()、values()、entrySet()
HashMap 關鍵特性
- 基於雜湊表、無序 (JDK 1.8+ 紅黑樹優化)
- 允許
null key (僅一個) 與 null value
- 非線程安全、高效能
完整 CRUD 實戰代碼
public class MapTest {
private Map<String, Student> students = new HashMap<>();
// 新增/修改 (put 覆蓋語義)
public void testPut() {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.print("輸入學生ID: ");
String id = sc.next();
if (students.containsKey(id)) {
System.out.println("ID 已存在");
continue;
}
System.out.print("輸入姓名: ");
String name = sc.next();
students.put(id, new Student(id, name));
System.out.println("新增成功: " + students.get(id).name);
}
}
// 遍歷方式一:keySet
public void testKeySet() {
System.out.println("總計: " + students.size() + " 人");
for (String id : students.keySet()) {
System.out.println("學生: " + students.get(id).name);
}
}
// 遍歷方式二:entrySet (推薦、效能更好)
public void testEntrySet() {
System.out.println("總計: " + students.size() + " 人");
for (Map.Entry<String, Student> entry : students.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue().name);
}
}
// 刪除
public void testRemove() {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.print("輸入要刪除的ID: ");
String id = sc.next();
Student s = students.remove(id);
if (s == null) System.out.println("不存在");
else { System.out.println("已刪除: " + s.name); break; }
}
}
// 修改
public void testModify() {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.print("輸入要修改的ID: ");
String id = sc.next();
Student s = students.get(id);
if (s == null) { System.out.println("不存在"); continue; }
System.out.println("當前姓名: " + s.name);
System.out.print("輸入新姓名: ");
String name = sc.next();
students.put(id, new Student(id, name));
System.out.println("修改成功"); break;
}
}
public static void main(String[] args) {
MapTest mt = new MapTest();
mt.testPut();
mt.testKeySet();
mt.testRemove();
mt.testEntrySet();
mt.testModify();
mt.testEntrySet();
}
}
執行結果示例
輸入學生ID: 1
輸入姓名: Tom
新增成功: Tom
輸入學生ID: 2
輸入姓名: Jack
新增成功: Jack
輸入學生ID: 3
輸入姓名: Lucy
新增成功: Lucy
總計: 3 人
學生: Tom
學生: Jack
學生: Lucy
輸入要刪除的ID: 12
不存在
輸入要刪除的ID: 3
已刪除: Lucy
總計: 2 人
Key: 1, Value: Tom
Key: 2, Value: Jack
輸入要修改的ID: 2
當前姓名: Jack
輸入新姓名: Lisa
修改成功
總計: 2 人
Key: 1, Value: Tom
Key: 2, Value: Lisa
遍歷效能對比
| 方式 | 時間複雜度 | 推薦場景 |
| keySet + get | O(n) 但兩次查找 | 僅需 key 或簡單邏輯 |
| entrySet | O(n) 單次查找 | 通用首選、需同時取 key/value |
| values | O(n) | 僅需 value |
| forEach (JDK8) | O(n) | map.forEach((k,v)->...) 代碼簡潔 |
常見陷阱
map.get(key) == null 無法區分「key 不存在」vs「value 為 null」→ 用 containsKey
- 迭代中修改結構 (put/remove) 拋
ConcurrentModificationException → 用 Iterator.remove() 或收集後批量處理
- 多執行緒環境用
ConcurrentHashMap