hashMap 原始碼解析

2021-08-31 01:13:16 字數 2787 閱讀 7302

這幾天跳槽 被人問得最多的問題就是基礎方面的知識..當時學習的時候有點囫圇吞棗..現在回頭把這些基本的集合類原始碼都仔細閱讀下

hashmap 用的是最頻繁的.. 所以問得也最多了.

initcapacity  初始化的容量   

loadfacotr    負載因子 主要用來計算threshold的值

threshold      閥值

這幾個關鍵屬性主要在建構函式中賦值.. 受影響的地方是resize方法.. 

// 這個預設的建構函式 

public hashmap()

final v putval(int hash, k key, v value, boolean onlyifabsent,

boolean evict)

if (e.hash == hash &&

((k = e.key) == key || (key != null && key.equals(k))))

break;

p = e;}}

v oldvalue = e.value;

if (!onlyifabsent || oldvalue == null)

e.value = value;

afternodeaccess(e);

return oldvalue;}}

++modcount;

if (++size > threshold)

resize();

afternodeinsertion(evict);

return null;

}

主要流程如下 如有偏差請指正

大體如上面的流程 有幾個老會被問的點.. 乙個是如何取下標..  乙個是resize如何rehash 

1 是如何計算下標的..   **中使用的是 (n-1) & hash   n是table.length 其實就是取模..當然n要是2的冪 

因為 n是2的冪 則說明 n的二進位制只有乙個數是1 其他都是0  n-1的話 那就是有(加入n=2^x) 則有 x個1.. 任意數字y與x個1與運算結果是x個1範圍內的1.. 超出x位的都是0 與後也是0 

n-100000000 0 0 

111111

hash 

11111111 11

101011     

取與的話其實只要關注紅色位置的與結果  其他位置因為n-1都是0 所以結果也是0

00000000 00 101011  結果就是這麼多了.. 綠色的部分其實就是n的倍數嘛..  這樣把倍數全部去掉剩下的就是餘數了。

2  在resize 中也有對應的操作

在resize 的時候需要將老陣列中的元素都移到新的陣列中.. 這個時候就需要重新計算元素的位置.. 

resize中的實現是  hash & n     n是 oldtable.length; 如果是 1 則需要移動到新的位置上面 新的位置是index+n

如果是0 則不需要移動位置... index 還是原來的位置...為什麼呢.. 

因為我們在擴容的時候是按一倍類擴容的.. 那計算index的時候則是

2n-1 

00000000 01

111111

hash

11111111 11

101011  rs

00000000 01

101011 n

00000000 01

000000

這個時候我們其實只需要比較 第7個1與上我們的hash對應的第7個1 是否是1    剛好第幾個1就是oldtab.lengh的值

因為我們只需要乙個位置的結果則用n與上hash 就可以了。

final node resize() 

// 沒超過最大值,就擴充為原來的2倍

else if ((newcap = oldcap << 1) < maximum_capacity &&

oldcap >= default_initial_capacity)

newthr = oldthr << 1; // double threshold

}else if (oldthr > 0) // initial capacity was placed in threshold

newcap = oldthr;

else

// 這裡傳遞了initcapactiy 則會跑到這裡來.. 還有就是擴充了幾次然後沒有超過

// default_initial_capacity的時候也會來這裡

if (newthr == 0)

threshold = newthr;

@suppresswarnings()

node newtab = (node)new node[newcap];

table = newtab;

if (oldtab != null)

// 原索引+oldcap

else

} while ((e = next) != null);

// 原索引放到newtable裡

if (lotail != null)

// 原索引+oldcap放到newtable裡

if (hitail != null) }}

}}return newtab;

}

3 hash中的紅黑樹.. 還是有點沒有徹底掌握

HashMap原始碼解析

以jdk1.8為例,hashmap是乙個用於儲存key value鍵值對的集合,每乙個鍵值對是乙個node jdk1.7叫做entry 後台是用乙個node陣列來存放資料,這個node陣列就是hashmap的主幹。這裡我們主要來分析hashmap的get和put方法。public v put k k...

HashMap原始碼解析

預設字段 static final int default initial capacity 1 4 預設node的陣列長度 16 static final int maximum capacity 1 30 陣列的最大長度 2 30 static final float default load ...

Hashmap原始碼解析

話不多說,直接看hashmap的put 方法原始碼 這是jdk1.8的原始碼 與1.7有所不同。final v putval int hash,k key,v value,boolean onlyifabsent,boolean evict if e.hash hash k e.key key ke...