2.hashmap基礎原始碼解析
鍊錶調整為紅黑樹的鍊錶長度閾值是什麼?
紅黑樹調整為鍊錶的鍊錶長度閾值是什麼?
鍊錶調整為紅黑樹的陣列最小閾值是什麼?
hashmap的陣列table儲存的就是乙個個的node型別,很清晰地看到有一對鍵值,還有乙個指向next的指標(以下只擷取了部分原始碼):
copystatic class
node
implements
map.entry
之前的**中在new物件時呼叫的是hashmap的無參構造方法,進入到該構造方法的原始碼檢視一下:
copypublic hashmap()
發現沒什麼內容,只是賦值了乙個預設載入因子;而在上文我們觀察到原始碼中table和size都沒有賦予初始值,說明剛建立的hashmap物件沒有分配容量,並不擁有預設的16個空間大小,這樣做的目的是為了節約空間,此時table為null,size為0。
當我們往物件裡新增元素時呼叫put方法:
copypublic v put
(k key, v value)
put方法把key和value傳給了putval,同時還傳入了乙個hash(key)所返回的值,這是乙個產生雜湊值的方法,再進入到putval方法(部分原始碼):
copyfinal v putval
(int hash, k key, v value,
boolean onlyifabsent,
boolean evict)
}
這裡面建立了乙個tab陣列和乙個node變數p,第乙個if實際是判斷table是否為空,而我們現在只關注剛建立hashmap物件時的狀態,此時tab和table都為空,滿足條件,執行內部**,這條**其實就是把resize()所返回的結果賦給tab,n就是tab的長度,resize顧名思義就是重新調整大小。檢視resize()原始碼(部分):
copyfinal node
resize()
@suppresswarnings()
node
newtab =
(node
)new
node
[newcap]
; table = newtab;
return newtab;
}
該方法首先把table及其長度賦值給oldtab和oldcap;threshold是閾值的意思,此時為0,所以前兩個if先不管,最後else裡newcap的值為預設初始化容量16;往下建立了乙個newcap大小的陣列並將其賦給了table,剛建立的hashmap物件就在這裡獲得了初始容量。然後我們再回到putval方法,第二個if就是根據雜湊碼得到的tab中的乙個位置是否為空,為空便直接新增元素,此時陣列中無元素所以直接新增。至此hashmap物件就完成了第乙個元素的新增。當新增的元素超過16*0.75=12時,就會進行擴容:
copyfinal v putval
(int hash, k key, v value,
boolean onlyifabsent,
boolean evict)
擴容的**如下(部分):
copyfinal node
resize()
elseif(
(newcap = oldcap <<1)
< maximum_capacity &&
oldcap >= default_initial_capacity)
}}
核心部分是else if裡的移位操作,也就是說每次擴容都是原來大小的兩倍。
注*:額外說明的一點是在jdk1.8以前鍊錶是頭插入,jdk1.8以後鍊錶是尾插入。
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 ...