1. 程式人生 > 其它 >HashMap,HashTable比較

HashMap,HashTable比較

HashTable操作

HashTable的操作幾乎和HashMap一致,主要的區別在於HashTable為了實現多執行緒安全,在幾乎所有的方法上都加上了synchronized鎖,而加鎖的結果就是HashTable操作的效率十分低下

HashTable與HashMap對比

(1)執行緒安全:HashMap是執行緒不安全的類,多執行緒下會造成併發衝突,但單執行緒下執行效率較高;HashTable是執行緒安全的類,很多方法都是用synchronized修飾,但同時因為加鎖導致併發效率低下,單執行緒環境效率也十分低;

(2)插入null:HashMap允許有一個鍵為null,允許多個值為null

;但HashTable不允許鍵或值為null

(3)容量:HashMap底層陣列長度必須為2的冪,這樣做是為了hash準備,預設為16;擴容為2倍

      而HashTable底層陣列長度可以為任意值,這就造成了hash演算法散射不均勻,容易造成hash衝突,預設為11;擴容為2n+1

     擴容詳見:擴容機制

(4)Hash對映:HashMap的hash演算法通過非常規設計,將底層table長度設計為2的冪,使用位與運算代替取模運算,減少運算消耗;而HashTable的hash演算法首先使得hash值小於整型數最大值,再通過取模進行散射運算;

(5)擴容機制HashMap建立一個為原先2倍的陣列,然後對原陣列進行遍歷以及rehash;HashTable擴容將建立一個原長度2倍的陣列,再使用頭插法將連結串列進行反序;

  • capacity 即容量,預設16
  • loadFactor載入因子,預設是0.75
  • threshold 閾值。閾值=容量*載入因子。預設12。當元素數量超過閾值時便會觸發擴容

    HashMap的容量變化通常存在以下幾種情況:

    1. 空引數的建構函式:例項化的HashMap預設內部陣列是null,即沒有例項化。第一次呼叫put方法時,則會開始第一次初始化擴容,長度為16。
    2. 有參建構函式:用於指定容量。會根據指定的正整數找到不小於指定容量的2的冪數,將這個數設定賦值給閾值(threshold)。第一次呼叫put方法時,會將閾值賦值給容量,然後讓。(因此並不是我們手動指定了容量就一定不會觸發擴容,超過閾值後一樣會擴容!!)
    3. 如果不是第一次擴容,則容量變為原來的2倍,閾值也變為原來的2倍。(容量和閾值都變為原來的2倍時,負載因子還是不變)

    此外還有幾個細節需要注意:

    • 首次put時,先會觸發擴容(算是初始化),然後存入資料,然後判斷是否需要擴容;
    • 不是首次put,則不再初始化,直接存入資料,然後判斷是否需要擴容;

(6)結構區別:HashMap是由陣列+連結串列形成,在JDK1.8之後連結串列長度大於8時轉化為紅黑樹;而HashTable一直都是陣列+連結串列;

(7)繼承關係:HashTable繼承自Dictionary類;而HashMap繼承自AbstractMap類;

(8)迭代器:HashMap是fail-fast(檢視之前HashMap相關文章);而HashTable不是。