JDK HashTable詳解

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


HashTable繼承關(guān)系圖

為了方便比較同時放出HashMap的繼承關(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()也可以達到想用的效果,但是為什么不用它呢

主要原因如下圖所示:


0x7FFFFFFF 和Math.abs()的區(qū)別

計算結(jié)果

可以看到當(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • HashMap 是 Java 面試必考的知識點,面試官從這個小知識點就可以了解我們對 Java 基礎(chǔ)的掌握程度。網(wǎng)...
    野狗子嗷嗷嗷閱讀 6,805評論 9 107
  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,887評論 0 11
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,628評論 18 399
  • 一、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,436評論 0 16
  • 千彎百轉(zhuǎn)九天上,連云寺上連云天。 東塘北塘收眼底,庇佑漳河福綿綿。
    跡遠留香閱讀 801評論 0 0

友情鏈接更多精彩內(nèi)容