在海量資料查找場景中,Hashtable(哈希表)是實現高效存取的關鍵資料結構。Java 提供了 java.util.Hashtable 與 java.util.HashMap 兩大核心實作,本文將從底層原理、核心 API、鍵值對象要求、擴容機制、執行緒安全性到效能調優,為您全方位剖析。
假設有 1,000 筆客戶資料,若以線性搜尋,平均需比對 500 次。哈希表透過雜湊函數將鍵映射到固定數量的「桶位」,將查找複雜度從 O(n) 降至接近 O(1)。核心在於:好的雜湊函數能讓資料均勻分佈,避免特定桶位過長導致退化為線性搜尋。
| 特性 | Hashtable | HashMap |
|---|---|---|
| 繼承體系 | extends Dictionary | implements Map (Java 1.2+) |
| 執行緒安全 | 所有方法 synchronized | 非同步,需外部同步或用 Collections.synchronizedMap |
| 允許 null 鍵/值 | 不允許 | 允許一個 null 鍵、多個 null 值 |
| 效能 | 同步開銷大 | 單執行緒下更快 |
| 迭代器 | Enumeration (fail-safe) | Iterator (fail-fast) |
建議: 現代開發優先使用 HashMap,需同步時再包裝;Hashtable 僅用於維護舊代碼。
Hashtable<String, BookRecord> table = new Hashtable<>();
// 存入
table.put("0-345-40946-9", new BookRecord("Einstein", "Relativity"));
// 取出
BookRecord br = table.get("0-345-40946-9");
// 移除
table.remove("0-345-40946-9");
自定類別作為鍵時,必須同時覆寫 這兩個方法:
equals():逐欄位比較業務邏輯上的相等性。hashCode():相等對象必須產生相同雜湊碼;不相等對象盡量分散,減少碰撞。JDK 內建類別(String、Integer、Long 等)已正確實作,可直接當鍵使用。
建構子 Hashtable(int initialCapacity, float loadFactor) 控制擴容閾值:
rehash()(容量變為 2×old+1)。調優技巧: 若預估資料量約 1,000 筆,可直接 new Hashtable(2000, 0.9f) 避免多次擴容;嵌入式裝置可設極大負載因子(如 100)犧牲查找速度換取記憶體與 CPU。
java.util.Properties 繼承 Hashtable,專門處理 String 鍵值對,提供 load()/store() 直接讀寫設定檔。切記: 僅使用 setProperty/getProperty,勿用父類 put/get 放入非字串物件,否則 store() 會失敗。
initialCapacity 減少 rehash。HashMap;多執行緒用 ConcurrentHashMap(分段鎖,效能優於同步 HashMap)。hashCode(),避免熱點桶位。remove() 不會自動縮容,長期運行需手動重建或換用弱引用 Map。掌握哈希表原理與 Java 實作細節,能幫助您在高併發、大數據場景下寫出更穩健、高效的程式碼。