基於JDK1 7的HashMap原始碼閱讀分析

2021-08-18 01:49:23 字數 1877 閱讀 3007

此版本是基於jdk1.7的hashmap。

hashmap的資料結構是陣列加單向鍊錶。

建立hashmap時,陣列長度預設值為16,最終呼叫的構造方法如下:

public hashmap(int initialcapacity, float loadfactor)

陣列的長度capacity為2的n次冪。也就是說,即便建立hashmap時,指定的長度為15,但是實際建立的結果也會是15的下乙個2的整數次冪,也就是16;

這裡還有乙個關鍵的屬性

threshold

,該屬性關係到hashmap何時擴容。

threshold

值由陣列長度*載入因子(

loadfactor預設值為0.75

)得來。

為什麼說hashmap裡每個資料的元素是個單向鍊錶,是由於hashmap的內部類entry的結構所致

static class entryimplements map.entry

.....

}每個enty包含乙個他的下乙個元素的指標,來構成單向鍊錶結構。hashmap裡儲存的k,v,實際就是entry的k,v

hashmap的put方法

。public v put(k key, v value)

}modcount++;

addentry(hash, key, value, i);

return null;

}putfornullkey(value)方法使的hashmap可以儲存key為null的資料,並且會存在entry[0]這列,且hash值為0;

hash(key)方法計算key的hash值。

indexfor(hash, table.length)方法來計算該entry在陣列中的位置,

static int indexfor(int h, int length)

假如hashmap的桶(entry陣列)長度為16(0001 0000),此時要存的entry的key的hash值為31(0001 1111)

那麼就會得出,此entry在桶中的位置為(0001 1111)&(0000 1111)=(0000 1111)即15。這個方法實際是用來快速取餘數(只對被除數為2的整數次冪有效,這也是為什麼hashmap中桶的長度為2的整數次冪

)。for (entrye = table[i]; e != null; e = e.next)

}modcount++;

addentry(hash, key, value, i);

return null;

剩下的**,會在table[i]這個單向鍊錶中尋找entry所在的位置,如果有相同的entry,則覆蓋並返回原來的值;如果沒有,則呼叫addentry方法。

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

createentry(hash, key, value, bucketindex);}呼叫

addentry方法時,會涉及到擴容問題。這跟上面提到的

threshold

有關,threshold=

桶的長度*載入因子(

loadfactor預設值為0.75

),當我們預設建立乙個桶的長度

為16,

載入因子為0.75的hashmap時,threshold為12。也就是說當此hashmap含有12個entery以後,再加入entry,並且該桶中已經存在其他entry,就需要進行擴容(注:hashmap的size方法,返回的是

entry的個數)。為什麼需要擴容,主要是為了提公升獲取元素的效率。如果hashmap中的每個元素能平均分布在每個桶中,那麼獲取元素的時間複雜度為o(1)。但如果發生雜湊

碰撞,即有的桶中存在多個entry,那獲取entry還需要遍歷該鍊錶,會很耗時。

基於 JDK1 7 版本實現 HashMap

在jdk1.7中是用的 陣列 單鏈表實現的hashmap 前一篇我用了linkedlist 陣列實現,其實本質上差不多,只是沒有寫擴容這一塊的內容,今天來個原生的方式實現hashmap。hashmap擴容機制?擴容後會產生什麼影響?因為很多解釋都寫到注釋裡面了,就不分模組解釋了。hashmap只允許...

JDK1 7的HashMap死迴圈

為什麼在jdk1.7多執行緒情況下會很容易出現hashmap死迴圈,這個還是要根據它採取的擴容策略來看,它的擴容策略是頭插法,因此會導致這樣的問題。在jdk1.8改進為尾插法,但並不意味著尾插法能適應多執行緒併發的場景,我認為其最主要的考慮就是頭插法在正常情況下是與原來鍊錶順序相逆的,而尾插不會改變...

JDK1 7的HashMap原始碼解讀

default initial capacity 初始化容量,中為1 4 即為16。為什麼要這樣寫呢?maximum capacity 最大容量,中衛1 30 即為2的30次冪。30次冪的原因是 改屬性為int型別,int型別最大為4個位元組,共32個二進位制位,理論上可以向左移動31次,即31次冪...