3hashmap的底層原理

2021-10-03 11:55:42 字數 1238 閱讀 5396

在jdk1.6,jdk1.7中,hashmap採用位桶+鍊錶實現,hashmap 的例項有兩個引數影響其效能:「初始容量」 和 「載入因子」。初識容量是16的陣列,載入因子是0.75。(當容量 是雜湊表中桶的數量,初始容量 只是雜湊表在建立時的容量。載入因子 是雜湊表在其容量自動增加之前可以達到多滿的一種尺度。)當雜湊表中的條目數超出了載入因子與當前容量的乘積時,並且要存放的位置已經有元素了(hash碰撞),必須滿足這兩個條件,才要對該雜湊表進行 rehash 操作,會將容量擴大為原來兩倍。

而jdk1.8中,hashmap採用位桶+鍊錶+紅黑樹實現,當鍊表長度超過閾值(8),時,將鍊錶轉換為紅黑樹,這樣大大減少了查詢時間。

hashmap底層維護乙個陣列,陣列中的每一項都是乙個entry。而這個entry應該放在陣列的哪乙個位置上(這個位置通常稱為位桶或者hash桶,即hash值相同的entry會放在同一位置,用鍊錶相連),是通過key的hashcode來計算的。通過hash計算出來的值將會使用indexfor方法找到它應該所在的table下標:這個方法其實相當於對table.length取模。

當兩個key通過hashcode計算相同時,則發生了hash衝突(碰撞),hashmap解決hash衝突的方式是用鍊錶。

當發生hash衝突時,則將存放在陣列中的entry設定為新值的next(這裡要注意的是,比如a和b都hash後都對映到下標i中,之前已經有a了,當map.put(b)時,將b放到下標i中,a則為b的next,所以新值存放在陣列中,舊值在新值的鍊錶上

jdk1.8

一直到jdk7為止,hashmap的結構都是這麼簡單,基於乙個陣列以及多個鍊錶的實現,hash值衝突的時候,就將對應節點以鍊錶的形式儲存。

這樣子的hashmap效能上就抱有一定疑問,如果說成百上千個節點在hash時發生碰撞,儲存乙個鍊錶中,那麼如果要查詢其中乙個節點,那就不可避免的花費o(n)的查詢時間,這將是多麼大的效能損失。這個問題終於在jdk8中得到了解決。再最壞的情況下,鍊錶查詢的時間複雜度為o(n),而紅黑樹一直是o(logn),這樣會提高hashmap的效率。

jdk7中hashmap採用的是位桶+鍊錶的方式,即我們常說的雜湊鍊錶的方式,而jdk8中採用的是位桶+鍊錶/紅黑樹(有關紅黑樹請檢視紅黑樹)的方式,也是非執行緒安全的。當某個位桶的鍊錶的長度達到某個閥值的時候,這個鍊錶就將轉換成紅黑樹。

jdk8中,當同乙個hash值的節點數不小於8時,將不再以單鏈表的形式儲存了,會被調整成一顆紅黑樹(上圖中null節點沒畫)。這就是jdk7與jdk8中hashmap實現的最大區別。

HashMap底層原理

1.hashmap概述 hashmap是基於雜湊表的map介面的非同步實現。此實現提供所有可選的對映操作,並允許使用null值和null鍵。此類不保證對映的順序,特別是它不保證該順序恆久不變。2.hashmap的資料結構 注意,迭代器的快速失敗行為不能得到保證,一般來說,存在非同步的併發修改時,不可...

HashMap底層原理

hashmap實現map介面,非執行緒安全的,區別於concurrenthashmap。允許使用null值和null鍵,不保證對映的順序.底層資料結構是乙個 陣列 鍊錶 紅黑樹 put 根據key計算得到key.hash h k.hashcode h 16 根據key.hash計算得到桶陣列的索引i...

HashMap底層原理

預設負載因子 static final float default load factor 0.75f 無參構造 public hashmap 有參構造 public hashmap int initialcapacity public hashmap int initialcapacity,flo...