再讀HashMap原始碼

2021-10-02 15:11:18 字數 2809 閱讀 4523

今天被問了hashmap的原始碼,雖然之前看過,但是時間一長,而且當時沒有做任何筆記,回答非常的模糊,所以決定回頭再讀一次。

hashmap預設初始化大小為16

tatic final

int default_initial_capacity =

1<<

4;

最大容量為2^30

static

final

int maximum_capacity =

1<<

30;

預設裝載比率為75%,即達到容量的75%就會自動擴容

static

final

float default_load_factor =

0.75f

;

樹形化閾值,眾所周知,為了避免多個雜湊值相等的元素都聚集在同一條鍊錶中,導致查詢效率降低,jdk1.8用紅黑樹代替了鍊錶,但並不是完全代替,當某條鍊錶的節點個數大於8時,會將鍊錶轉為紅黑樹

static

final

int treeify_threshold =

8;

反之,當hashmap擴容是發現某條鍊錶節點個數小於6時,會將紅黑樹還原為鍊錶

static

final

int untreeify_threshold =

6;

當hashmap中的元素容量大於該值64時,上面所講的樹形化才會被執行

static

final

int min_treeify_capacity =

64;

下面記錄一下重點的幾個方法

resize()

//擴容方法

final node

resize()

//如果沒有超過且原有容量擴大一倍不大於最大容量

elseif(

(newcap = oldcap <<1)

< maximum_capacity &&

oldcap >= default_initial_capacity)

newthr = oldthr <<1;

//新的容量為原來的2倍

}else

if(oldthr >0)

// initial capacity was placed in threshold

//如果原容量為0且原map的可裝載元素數大於0,則用原可裝載數作為新map的最大容量

newcap = oldthr;

else

if(newthr ==0)

threshold = newthr;

//這裡初始化乙個新容量的map

@suppresswarnings()

node

newtab =

(node

)new

node

[newcap]

; table = newtab;

if(oldtab != null)

else

}while

((e = next)

!= null);if

(lotail != null)

if(hitail != null)}}

}}return newtab;

}

上乙個方法resize()中提到了根據某個桶內的元素個數對紅黑樹進行處理,用到的split()方法

final

void

split

(hashmap map, node[

] tab,

int index,

int bit)

else}if

(lohead != null)}if

(hihead != null)

}}

當鍊表元素個數大於閾值時,就會進行桶的樹形化treeifybin()

//將桶內所有的 鍊錶節點 替換成 紅黑樹節點

final

void

treeifybin

(node[

] tab,

int hash)

tl = p;

}while

((e = e.next)

!= null)

;//讓桶的第乙個元素指向新建的紅黑樹頭結點,以後這個桶裡的元素就是紅黑樹而不是鍊錶了if(

(tab[index]

= hd)

!= null)

hd.treeify

(tab);}

} treenode replacementtreenode

(node p, node next)

上乙個方法只是將鍊錶轉化為乙個二叉樹的結構,還沒有但是我們發現,並沒有設定紅黑樹的顏色值,現在得到的只能算是個二叉樹。在 最後呼叫樹形節點 hd.treeify(tab) 方法進行塑造紅黑樹

final

void

treeify

(node[

] tab)

else}}

}moveroottofront

(tab, root)

;}

可以看到,將二叉樹變為紅黑樹時,需要保證有序。這裡有個雙重迴圈,拿樹中的所有節點和當前節點的雜湊值進行對比(如果雜湊值相等,就對比鍵,這裡不用完全有序),然後根據比較結果確定在樹種的位置。

原始碼分析 HashMap原始碼再讀 基於Java8

最近工作不是太忙,準備再讀讀一些原始碼,想來想去,還是先從jdk的原始碼讀起吧,畢竟很久不去讀了,很多東西都生疏了。當然,還是先從炙手可熱的hashmap,每次讀都會有一些收穫。當然,jdk8對hashmap有一次優化 我們首先看到的,應該是它的一些基本引數,這對於我們了解hashmap有一定的作用...

再讀SIFT理論及原始碼

sift特徵點檢測及描述 引言 sift特徵點,尺度不變的特徵變換。其具有尺度不變性 高斯差分金字塔 旋轉不變性 主方向 部分放射不變性 在統計梯度方向直方圖時對直方圖進行了高斯平滑 sift特徵分為兩部分,第乙個是要檢測一幅影象中關鍵點的位置,第二個是要生成乙個描述子來表示這個點位置。名詞解釋 1...

HashMap原始碼系列 HashMap的屬性

public class hashmap extends abstractmap implements map,cloneable,serializable容載因子 容載因子越大,table陣列中儲存的資料越密集,碰撞的可能性就越大。容載因子越小,儲存越稀疏,碰撞的可能性就越小,不過浪費儲存空間。轉...