Hashtable 是 JDK 1.0 遗留類別,HashMap 是 JDK 1.2 集合框架引入的替代品。兩者皆實作 Map 介面,底層皆為雜湊表,但設計哲學截然不同。
| 維度 | Hashtable | HashMap |
|---|---|---|
| 同步化 | 所有 public 方法 synchronized,執行緒安全 | 非同步,高效能,非執行緒安全 |
| Null 鍵/值 | 不允許,拋出 NullPointerException | 允許一個 null key,多個 null value |
| 繼承體系 | 繼承 Dictionary 抽象類別 | 實作 Map 介面,繼承 AbstractMap |
| 迭代器 | Enumeration(舊式,不支援 remove) | Iterator(標準,支援 fail-fast) |
| 預設容量/擴容 | 11,擴容 2n+1 | 16,擴容 2n(倍增) |
| 雜湊算法 | 直接使用 key.hashCode() | 二次雜湊 hash(key.hashCode()) 減少碰撞 |
package com.test;
import java.util.*;
public class Demo7_3 {
public static void main(String[] args) {
Emp emp1 = new Emp("s001", "aaa", 12.3f);
// Hashtable 不允許 null
Hashtable<String, Emp> ht = new Hashtable<>();
ht.put("s001", emp1);
// ht.put(null, null); // 拋出 NullPointerException
// HashMap 允許 null
HashMap<String, Emp> hm = new HashMap<>();
hm.put(null, null); // 正常執行
System.out.println("HashMap null value: " + hm.get(null));
}
}
單執行緒 100 萬次 put/get 操作(JDK 11,Intel i7):
Collections.synchronizedMap(new HashMap<>())// JDK 8+ 推薦:無鎖 CAS + synchronized 細粒度鎖
Map<String, Emp> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.put("s001", emp1);
// 復合操作原子性
concurrentMap.computeIfAbsent("s002", k -> new Emp("s002", "bbb", 5.3f));
concurrentMap.merge("s001", empUpdate, (old, newVal) -> mergeLogic(old, newVal));
Hashtable 是歷史產物,同步化粒度粗、效能差、API 過時。HashMap 針對單執行緒高效能優化,配合 ConcurrentHashMap 解決並發需求,構成現代 Java Map 應用的雙支柱。深度理解兩者差異,是 Java 開發者進階的必修課。