HashMap是基於哈希表實現的,每一個元素是一個key-value對,其內部通過單鏈表解決沖突問題,容量不足(超過了閥值)時,同樣會自動增長。HashMap和HashTable都使用哈希表來存儲鍵值對。在數據結構上是基本相同的,都創建了一個繼承自Map.Entry的私有的內部類Entry,每一個Entry對象表示存儲在哈希表中的一個鍵值對。
Hashtable繼承自Dictionary類,而HashMap繼承自AbstractMap類。但二者都實現了Map接口。
兩者計算hash的方法不同:
Hashtable計算hash是直接使用key的hashcode對table數組的長度直接進行取模:
int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length;
HashMap計算hash對key的hashcode進行了二次hash,以獲得更好的散列值,然后對table數組長度取摸: static int hash(int h) { h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } static int indexFor(int h, int length) { return h & (length-1); }
HashMap和HashTable都實現了Serializable接口,因此它支持序列化,實現了Cloneable接口,能被克隆。
HashMap的初始容量為16,Hashtable初始容量為11,兩者的填充因子默認都是0.75。
HashMap擴容時是當前容量翻倍即:capacity*2,Hashtable擴容時是容量翻倍+1即:capacity*2+1。
HashMap是非線程安全的,只是用於單線程環境下,多線程環境下可以采用concurrent並發包下的concurrentHashMap。HashTable是線程安全的。
HashMap中key和value都允許為null。key為null的鍵值對永遠都放在以table[0]為頭結點的鏈表中。HashTable在遇到null時,會拋出NullPointerException異常。
HashMap僅支持Iterator的遍歷方式,Hashtable支持Iterator和Enumeration兩種遍歷方式。
判斷是否含有某個鍵 :
在HashMap 中,null 可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對
應的值為null。當get()方法返回null 值時,既可以表示HashMap 中沒有該鍵,也可
以表示該鍵所對應的值為null。因此,在HashMap 中不能用get()方法來判斷HashM
ap 中是否存在某個鍵,而應該用containsKey()方法來判斷。Hashtable 的鍵值都不能
為null,所以可以用get()方法來判斷是否含有某個鍵。