HashMap底層資料結構

2022-09-16 05:12:10 字數 1538 閱讀 3986

jdk1.8之前:陣列+鍊錶

jdk1.8之後:陣列+鍊錶+紅黑樹

陣列的時間複雜度:o(1)

鍊錶的時間複雜度:o(n)

紅黑樹時間複雜度:o(logn)

為什麼使用陣列?

陣列的的讀、寫速度快。(查詢快,增刪慢)

為什麼使用鍊錶?

為了避免資料的key產生雜湊碰撞後將原有的陣列下標對應的值直接替換。(查詢慢,增刪快)

為什麼使用紅黑樹?

為了解決鍊錶過長效能低的問題,增加查詢,插入,刪除的效率。

hashmap的put()和get()的實現:

map.put(k,v)實現原理

1.先將k、v封裝到node物件當中;

2.底層呼叫k的hashcode()方法計算出hash值;

3.(return h & (length-1))h代表hash值,length代表hashmap的容量

通過取模演算法計算出陣列的下標,如果下標的位置上沒有元素,就會把node新增到這個位置上,

如果下標的位置上有鍊錶,就會呼叫object中的equals方法將node中k和鍊錶中每個節點的k進行比較,相同會直接覆蓋,不相同會新增到鍊錶的末尾。

當單向鍊錶資料結構長度大於8時,會形成紅黑樹資料結構,增加效能。當紅黑樹上的節點數量小於6個,會重新把紅黑樹變成單向鍊錶資料結構。

map.get(k)實現原理

1.底層呼叫k的hashcode()方法計算出hash值;

2.通過hash值用取模演算法計算出陣列下標,快速定位到某個位置上,如果該位置上沒有值,直接返回null,

如果該位置上由單向鍊錶,就會呼叫object中的equals方法將node中k和鍊錶中每個節點的k進行比較,

如果equals方法返回false,則get結果為null,如果equals方法返回true,則get結果為該節點的value。

hashmap初始容量為什麼是16?

基於效率和記憶體使用上的乙個權衡值;

太大了浪費空間,太小了,頻繁擴容,影響效率。

為什麼載入因子為0.75f?

因為0.75正好是3/4,而容量又是2的冪,兩個數的乘積始終為整數

紅黑樹的平均查詢長度是log(n),長度為8,查詢長度為log(8)=3,鍊錶的平均查詢長度為n/2,當長度為8時,平均查詢長度為8/2=4,這才有轉換成樹的必要;

鍊錶長度如果是小於等於6,6/2=3,雖然速度也很快的,但是轉化為樹結構和生成樹的時間並不會太短。

還有選擇6和8的原因是:

中間有個差值7可以防止鍊錶和樹之間頻繁的轉換。假設一下,如果設計成煉表個數超過8則鍊錶轉換成樹結構,鍊錶個數小於8則樹結構轉換成鍊錶,如果乙個hashmap不停的插入、刪除元素,鍊錶個數在8左右徘徊,就會頻繁的發生樹轉鍊錶、鍊錶轉樹,效率會很低。

回顧 HashMap的底層資料結構

假設一段 hashmap map newhashmap map.put 張三 測試資料 map.put 李四 測試資料 對張三這個key,計算出hash值,對hash值進行取模處理,定位到陣列裡的乙個元素中去 張三,測試資料 李四,測試資料 如 map.put 張三 測試資料 對 張三 這個key計...

初步了解HashMap底層資料結構

本文主要講述hashmap的一些簡單原理,如果講的不好,可以說出來,讓我改正本文。說到hashmap的資料結構,就需要說到資料結構中的陣列和單鏈表結構,因為hashmap的底層就是陣列和鍊錶,不過這是jdk1.7版本的,1.8版本後加入了紅黑樹。下面先介紹一些這些資料結構。陣列儲存區間是連續的,占用...

redis set底層資料結構

redis的集合物件set的底層儲存結構特別神奇,我估計一般人想象不到,底層使用了intset和hashtable兩種資料結構儲存的,intset我們可以理解為陣列,hashtable就是普通的雜湊表 key為set的值,value為null 是不是覺得用hashtable儲存set是一件很神奇的事...