先上HashTable的繼承關(guān)系:

為了方便比較同時放出HashMap的繼承關(guān)系:

可以看出HahMap和HashTable都實現(xiàn)了Map接口,只是父類不一樣
HashTable的計算哈希是直接取得key本身的哈希:
int hash = key.hashCode();
這里可以看出,hashtable是不支持null值的,并且在put的時候取哈希之前已經(jīng)判定了value為空判定,雖然key沒有判定,但是在取hash的時候由于key是null所以一定會拋出java.lang.NullPointerException
if (value == null) {
throw new NullPointerException();
}
HashTable每次擴容是原有容量的2倍+1( (oldCapacity << 1) + 1),通過rehash()來實現(xiàn)擴容的
HashTable是的每個哈希桶的元素都是鏈表,相對來說如果每個哈希桶元素比較多的話,處理效率是比較低的,接下來劃重點,這實質(zhì)就是哈希表的實質(zhì),一張課表

我們首先取得今天的日期,比如星期三,然后一節(jié)一節(jié)比較,尋找文體活動這門課,畢竟大家都不喜歡上課,過程和HashTable完全一致
哈希桶就相當(dāng)于一個表格,首先從X軸取得哈希桶位置再在Y軸比較獲取元素真實位置。
HashTable的計算索引的方式是:
(hash & 0x7FFFFFFF) % tab.length
這里為什么要與0x7FFFFFFF是因為Hash的值會是負數(shù),0x7FFFFFFF是Integer.MAX_VALUE,使用Math.abs()也可以達到想用的效果,但是為什么不用它呢
主要原因如下圖所示:


可以看到當(dāng)hash為Integer的最小值的時候,會導(dǎo)致Math.abs取得負數(shù)值,這樣計算出來的index下標(biāo)也是負值,而java的數(shù)組下標(biāo)不能為負數(shù),否則會導(dǎo)致程序異常
最終將node追加到哈希哈希桶某個哈西位置的尾部,就完成了整個存儲過程
需要注意的是:HashTable是線程安全的,HashTable所有public方法都添加了synchronized關(guān)鍵字,保證線程同步不會出錯。但是同時因為線程安全機制導(dǎo)致HashTable的存取效率不如HashMap
比較上一篇文章 JDK HashMap詳解 而言,HashTable雖然都實現(xiàn)了Map接口,但各自有著不同的應(yīng)用場景,總結(jié)起來有如下不同點:
- HashTable是線程安全的,HashMap是線程不安全的
- HashTable允許K,V均可以為null,但是HashMap不能為null,否則會有空指針異常
- 計算Hash的方式不同,HashTable計算哈希的方式是直接取key本身的hash,而HashMap計算hash的方式為:(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16) 自身哈希和哈希無符號右移16位做與運算,之所以會有這種差異是因為HashTable和HashTable計算索引方式不同,HashTable直接與當(dāng)前長度取余獲取當(dāng)前索引,而HashMap通過公式((size - 1) & hash)計算索引值
- 數(shù)據(jù)結(jié)構(gòu)不同:HashTable采用的是鏈表形式,而HashMap采用的是閾值以下用鏈表閾值以上用紅黑樹的數(shù)據(jù)結(jié)構(gòu)
- 存取效率:HashTable的效率相對比較低,因為有synchronized關(guān)鍵字做線程同步,HashMap存取效率比較高,因為沒有鎖的限制,但因為其不是線程安全的,在線程安全場景下需要進行一些線程同步操作
- 在查詢包含關(guān)系的時候,HashTable提供的是contains(),containsKey()和containsValue()方法,而hashMap把只有兩個分別為:containsKey()和containsValue()
- HashTable是官方建議被替換的以下來自于JDK8中的注釋
If a thread-safe implementation is not needed, it is recommended to use
{@link HashMap} in place of {@code Hashtable}. If a thread-safe
highly-concurrent implementation is desired, then it is recommended
to use {@link java.util.concurrent.ConcurrentHashMap} in place of
{@code Hashtable}.
大致含義為:如果你不需要線程同步,建議使用HashMap來代替HashTable,如果你的你是需要線程同步的話使用ConcurrentHashMap來替代Hashtable