HashMap源碼小解析

                 文章版權歸katherine所有,請隨意轉載

一.HashMap概述

基于哈希表的 Map 接口的實現。此實現提供所有可選的映射操作, 并允許使用 null 值和 null 鍵。此類不保證映射的順序,特別是它不保 證該順序恒久不變。

二.HashMap的數據結構

Jdk1.8中的結構示意圖

這里寫圖片描述

在JDK1.8之前,HashMap采用桶+鏈表實現,本質就是采用數組+單向鏈表組合型的數據結構。它之所以有相當 快的查詢速度主要是因為它是通過計算散列碼來決定存儲的位置。HashMap通過key的hashCode來計算hash值,不同的hash值就存在數組 中不同的位置,當多個元素的hash值相同時(所謂hash沖突),就采用鏈表將它們串聯起來(鏈表解決沖突),放置在該hash值所對應的數組位置上。
在JDK1.8中,HashMap的存儲結構已經發生變化,它采用數組+鏈表+紅黑樹這種組合型數據結構。當hash值發生沖突時,會采用鏈表或者紅黑樹解決沖突。當同一hash值的結點數小于8時,則采用鏈表,否則,采用紅黑樹。

通過key的hashCode來計算hash值再計算下標值
只要hashCode相同,計算出來的hash值就一樣
就有可能不同的對象所算出來的hash值是相同的,這就出現了所謂的hash沖突解決沖突示意圖如下


這里寫圖片描述

在看源碼之前我們先看一下源碼中涉及的關鍵屬性:

三.關鍵屬性

capacity
capacity譯為容量。capacity就是指HashMap中桶的數量。默認值為16。一般第一次擴容時會擴容到64,之后是2倍。總之,容量都是2的冪。
loadFactor
loadFactor譯為裝載因子。裝載因子用來衡量HashMap滿的程度。loadFactor的默認值為0.75f。計算HashMap的實時裝載因子的方法為:size/capacity
size
size表示HashMap中存放node的數量就是所有的鍵值對的數量
threshold
threshold表示當HashMap的size大于threshold時會執行resize(擴容)操作。 ?threshold=capacity*loadFactor

四.HashMap的四種構造方法

A.默認的構造方法public HashMap()
容量 = 16
裝載因子=0.75
B.自定義容量publicHashMap(intinitialCapacity)
this(initialCapacity, DEFAULT_LOAD_FACTOR);
調用了重載方法 傳入了自定義容量和默認的加載因子
C.自定義容量和裝載因子publicHashMap
(intinitialCapacity,floatloadFactor)
要判斷傳入的自定義容量是否合法
重新計算閾值
D.構造一個映射關系與指定map相同的HashMap
public HashMap(Map<? extends K, ? extends V> m)

HashMap中有幾個特別重要的函數,這篇博客也是主要涉及了幾個比較重要的函數

四.hash()函數

這里寫圖片描述

四.resize()函數

這里寫圖片描述

五.put( )操作

把源碼用流程圖的方式展示出來了 可以對比源碼來看這個流程圖,或者之后補上加注釋的代碼


這里寫圖片描述

這里寫圖片描述

這里寫圖片描述

插入成功還要給size+1
然后判斷是否超過閾值 需不需要擴容

總結put操作
1、(n - 1) & hash 確定元素存放在哪個桶中,桶為空,新生成結點放入桶中(此時,這個結點是放在數組中).
2、若桶中已經存在元素,則比較桶中第一個元素(數組中的結點)的hash值,key值
a).hash值相等,key相等,則將第一個元素賦值給e,用e來記錄。
b).hash值不相等,即key不相等;為鏈表結點,從尾部插入新節點
c).若結點數量達到閾值,轉化為紅黑樹。
返回null或者被覆蓋的value

六.get( )操作

這里寫圖片描述

這里寫圖片描述

總結get操作
1.桶中第一項(數組元素)hash值相等,key相等;則取第一個的值
2.若桶中已經存在元素,則比較桶中第一個元素(數組中的結點)的hash值,key值
a).若為紅黑樹結點,在紅黑樹中查找。
b).若為鏈表結點,在鏈表中查找。

七.為什么每次擴容都是二倍

為了效率 里面的運算都是位運算
那位運算是基于二進制的
然后(n-1)&hash這里就是一個典型的
初始n= 16 在減一之后是15(16的余數結果就在0-15之間)
然后與hash值做與運算的時候才能起到求余的效果
00000000 00000000 00000000 00001111
00000000 00000000 00000000 01011011
當你擴大為2的n次冪時
永遠都可以通過減一得到低位全部為1的結果
那與任何數做與運算的時候都可以快速的得到取余結果
所以說當length = 2^n時,不同的hash值發生碰撞的概率比較小,這樣就會使得數據在table數組中分布較均勻,查詢速度也較快。

八.最后

hashmap涉及了很多的位運算和紅黑樹的操作,反正也是看的很暈
以上肯定也有很多錯誤
不過都看到這里了就給個喜歡唄 啾

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容