HashMap的原始碼分析

2021-09-19 04:40:29 字數 3500 閱讀 5828

hashmap是乙個雜湊表, 它儲存的內容是鍵值對(key - value)對映。

hashmap繼承於abstractmap, 實現了mapcloneableserializable介面。

hashmap不是執行緒安全的, 不適用於多執行緒中, 此外,hashmap中的對映不是有序的。

hashmap裡面是乙個陣列,然後陣列中每個元素是乙個單項鍊表。

圖中entry包含四個屬性,keyvaluehash值和用於單項鍊表的next

key值允許為空,value允許為空。

/**

* 允許空的key值

*/public

static

void

putkeynull()

/** * 允許空的value值

*/public

static

void

putvaluenull()

執行結果:

entryset==

==key==

==null==

==value====1

====hash====0

entryset==

==key====1

====value==

==null==

==hash==

==49

重要引數capacityloadfactor

capacity當前陣列容量,始終保持 2^n,預設值為1<<4,最大為1<<16, 可以擴容,擴容後陣列大小為當前的 2 倍。

loadfactor負載因子,預設為 0.75。

threshold擴容的閾值,等於capacity * loadfactor

static

final

int default_initial_capacity =

1<<4;

static

final

int maximum_capacity =

1<<30;

static

final

float default_load_factor =

0.75f

;

hashmapput方法:

public v put

(k key, v value)

//第三個引數 onlyifabsent 如果是 true,那麼只有在不存在該 key 時才會進行 put 操作

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;}}

// e!=null 說明存在舊值的key與要插入的key"相等"

// 對於我們分析的put操作,下面這個 if 其實就是進行 "值覆蓋",然後返回舊值

if(e != null)

}++modcount;

// 如果 hashmap 由於新插入這個值導致 size 已經超過了閾值,需要進行擴容if(

++size > threshold)

resize()

;afternodeinsertion

(evict)

;return null;

}接下來看 hashmap 的 resize 方法

final node

resize()

elseif(

(newcap = oldcap <<1)

< maximum_capacity &&

oldcap >= default_initial_capacity)

newthr = oldthr <<1;

// double threshold

}else

if(oldthr >0)

// 對應使用 new hashmap(int initialcapacity) 初始化後,第一次 put 的時候

newcap = oldthr;

else

// 用新的陣列大小初始化新的陣列

if(newthr ==0)

threshold = newthr;

@suppresswarnings()

node

newtab =

(node

)new

node

[newcap]

; table = newtab;

// 如果是初始化陣列,到這裡就結束了,返回 newtab 即可

if(oldtab != null)

else

}while

((e = next)

!= null);if

(lotail != null)

if(hitail != null)}}

}}return newtab;

}

hashmapget方法

1.計算keyhash值,根據hash值找到對應陣列下標:hash & (length-1)

2.判斷陣列該位置處的元素是否剛好就是我們要找的,如果不是,走第三步

3.判斷該元素型別是否是treenode,如果是,用紅黑樹的方法取資料,如果不是,走第四步

4.遍歷鍊錶,直到找到相等(==或equals)的 key

public v get

(object key)

final node

getnode

(int hash, object key)

while

((e = e.next)

!= null);}

}return null;

}

HashMap原始碼分析

public hashmap int initialcapacity,float loadfactor 2 接下來是重要的put方法,put方法用於將鍵值對儲存到map中,讓我們來具體分析一下。public v put k key,v value if key null 若key為null,則將va...

HashMap 原始碼分析

1 getentry object key 方法 final entrygetentry object key return null 根據key的hash值計算出索引,得到table中的位置,然後遍歷table處的鍊錶 for entrye table indexfor hash,table.le...

HashMap原始碼分析

public v put k key,v value if key null return putfornullkey value int hash hash key int i indexfor hash,table.length for entrye table i e null e e.nex...