HashMap 原始碼解析

2021-10-06 20:18:29 字數 4602 閱讀 9297

hashmap為map介面的乙個實現類,實現了所有map的操作。
public

class

hashmap

extends

abstractmap

implements

map, cloneable, serializable

map m =

newconcurrenthashmap()

;// 或者

map m = collections.

synchronizedmap

(new

hashmap()

);

//這兩個是限定值 當節點數大於8時會轉為紅黑樹儲存

static

final

int treeify_threshold =8;

//當節點數小於6時會轉為單向鍊錶儲存

static

final

int untreeify_threshold =6;

//紅黑樹最小長度為 64

static

final

int min_treeify_capacity =64;

//hashmap容量初始大小

static

final

int default_initial_capacity =

1<<4;

// aka 16

//hashmap容量極限

static

final

int maximum_capacity =

1<<30;

//負載因子預設大小

static

final

float default_load_factor =

0.75f

;//node是map.entry介面的實現類

//在此儲存資料的node陣列容量是2次冪

//每乙個node本質都是乙個單向鍊錶

transient node

table;

//hashmap大小,它代表hashmap儲存的鍵值對的多少

transient

int size;

//hashmap被改變的次數

transient

int modcount;

//下一次hashmap擴容的大小

int threshold;

//儲存負載因子的常量

final

float loadfactor;

​//預設的建構函式

public

hashmap()

//指定容量大小

public

hashmap

(int initialcapacity)

//指定容量大小和負載因子大小

public

hashmap

(int initialcapacity,

float loadfactor)

//傳入乙個map集合,將map集合中元素map.entry全部新增進hashmap例項中

public

hashmap

(map<

?extendsk,

?extends

v> m)

node 單向鍊錶的實現:
//實現了map.entry介面

static

class

node

implements

map.entry

​public

final k getkey()

public

final v getvalue()

public

final string tostring()

​public

final

inthashcode()

​public

final v setvalue

(v newvalue)

//equals屬性對比

public

final

boolean

equals

(object o)

return

false;}

}

treenode 紅黑樹實現:
static

final

class

treenode

extends

linkedhashmap.linkedhashmapentry

​/*** 根節點的實現*/

final treenode

root()

}...

1、 put方法原始碼實現:

public v put

(k key, v value)

的具體實現

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;

//p記錄下乙個節點}}

if(e != null)

}++modcount;if(

++size > threshold)

//判斷是否需要擴容

resize()

;afternodeinsertion

(evict)

;return null;

}

執行過程如下:

首先獲取node陣列table物件和長度,若table為null或長度為0,則呼叫resize()擴容方法獲取table最新物件,並通過此物件獲取長度大小

判定陣列中指定索引下的節點是否為null,若為null 則new出乙個單向鍊錶賦給table中索引下的這個節點

若判定不為null,我們的判斷再做分支

最後判定陣列大小需不需要擴容

2、get 方法原始碼實現:

public v get

(object key)

final node

getnode

(int hash, object key)

while

((e = e.next)

!= null);}

}return null;

}

執行過程如下:

判定三個條件 table不為null & table的長度大於0 & table指定的索引值不為null

2.判定 匹配hash值 & 匹配key值 成功則返回 該值

3.若 first節點的下乙個節點不為null

//重新設定table大小/擴容 並返回擴容的node陣列即hashmap的最新資料

final node

resize()

//若新表大小(oldcap*2)小於陣列極限大小 並且 老表大於等於陣列初始化大小

elseif(

(newcap = oldcap <<1)

< maximum_capacity &&

oldcap >= default_initial_capacity)

//舊陣列大小oldthr 經二進位制運算向左位移1個位置 即 oldthr*2當作新陣列的大小

newthr = oldthr <<1;

// double threshold

}//若老表中下次擴容大小oldthr大於0

else

if(oldthr >0)

newcap = oldthr;

//將oldthr賦予控制新錶大小的newcap

else

//若新表的下表下一次擴容大小為0

if(newthr ==0)

threshold = newthr;

//下次擴容的大小

@suppresswarnings()

node

newtab =

(node

)new

node

[newcap]

; table = newtab;

//將當前表賦予table

if(oldtab != null)

else

}while

((e = next)

!= null)

;//通過判定將舊資料和新資料儲存到新錶指定的位置

if(lotail != null)

if(hitail != null)}}

}}//返回新錶

return newtab;

}

hashmap.resize 函式執行過程如下:

HashMap原始碼解析

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

hashMap 原始碼解析

這幾天跳槽 被人問得最多的問題就是基礎方面的知識.當時學習的時候有點囫圇吞棗.現在回頭把這些基本的集合類原始碼都仔細閱讀下 hashmap 用的是最頻繁的.所以問得也最多了.initcapacity 初始化的容量 loadfacotr 負載因子 主要用來計算threshold的值 threshold...

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 ...