HashMap原始碼解讀

2021-07-06 03:11:46 字數 1917 閱讀 9591

一、建立乙個hashmap都做了哪些工作?

mapmap = new hashmap(); 

hahmap無參構造方法

public hashmap()
可以看到設定了載入因子(預設0.75)、閾值(預設容量16*預設載入因子0.75=12)、table是hashmap內部資料儲存結構entry陣列。當hashmap的size大於等於閾值時,hashmap會擴容到原來的容量的2倍。而如果 new hashmap(1),它的容量是不是1呢?可以看到最終呼叫的構造方法: 

public hashmap(int initialcapacity) :
最終呼叫的是下面的

public hashmap(int initialcapacity, float loadfactor)
可以看到hashmap的size總是2的倍數,即new hashmap(1)的最終容量是2.

entry是什麼呢?entry就是map中存放的key-value對,並且儲存了下乙個節點的引用next和key的hash值,也就實現了鍊錶的功能。

entry結構體:

hashmap儲存結構圖:

二、put(key,value)的實現

public v put(k key, v value) 

}modcount++;

addentry(hash, key, value, i);

return null;

}

hashmap允許存null key值,它會把key為null放到table[0]的位置,即第乙個bucket(table陣列中的元素稱為bucket桶)。

新增乙個新元素時,先根據key值計算出hash碼,根據hash碼計算出所在bucket的位置i。遍歷table[i]下掛的entry,如果key值存在就覆蓋value,不存在就新增新的entry。

void addentry(int hash, k key, v value, int bucketindex)

entry(int h, k k, v v, entryn)addentry方法中判斷容量是否超過閾值,若超過會擴容到原來的2倍大小。

void resize(int newcapacity)

entry newtable = new entry[newcapacity];

transfer(newtable);

table = newtable;

threshold = (int)(newcapacity * loadfactor);

}

擴容之後把原來的元素轉移過來,重新hash,重新分配bucket位置,同乙個bucket鏈結的entry會倒序鏈結起來。

void transfer(entry newtable)  while (e != null);}}

}

三、get(key)的實現

get就比較簡單,按照hash碼找到對應的bucket,遍歷掛載的entry,若key值相同就返回對應的value,若找不到就返回null。

public v get(object key) 

return null;

}

四、hash衝突處理方法

1、開放位址法

2、鏈位址法

hashmap處理hash衝突採用的鏈位址法

HashMap原始碼解讀

今日閒來無事,擷取一段hashmap的 分析一下 int hash hash key 根據key 的hashcode 計算hash值 int i indexfor hash,table.length 根據hash值 計算出再陣列中的位置 for entrye table i e null e e.n...

HashMap原始碼解讀

hashmap原始碼分析 me 對集合檢視的迭代,hashmap的桶數加實際大小與時間成正比,也就是說,不可以把桶樹設定的太多或負載因子太小。o 對集合檢視的迭代需要與hashmap 例項的 容量 桶數 加上其大小 鍵值對映的數量 成比例的時間。因此,如果迭代效能很重要,則不要將初始容量設定得太高 ...

HashMap原始碼解讀

public v put k key,v value static final int hash object key final v putval int hash,k key,v value,boolean onlyifabsent,boolean evict 如果在遍歷鍊錶中途,發現可以值相等...