首先,我們要了解一下hashmap的儲存方式
既然名字包含hash,不難看出他是以hash值作為位址儲存的,更確切的講他是以雜湊桶aka鏈位址的方式儲存元素的
如果不了解什麼是雜湊桶,或者想先看一下hashmap的實現特點參見——hashmap實現特點——基於jdk文件
雜湊衝突採用的是雜湊桶,桶中元素使用鍊錶儲存,但是如果元素過多,那麼就會採用樹的方式儲存。樹是hashmap中最重要的資料結構。
hashmap()構造方法
putval()方法
resize()方法
hashmap是按照下面圖示方式儲存元素(如果沒有雜湊衝突),乙個陣列,陣列中元素叫做節點也就是桶,所以首先我們需要了解節點。如果有雜湊衝突,那麼每個節點的桶就會存多個元素,文章下面有。
下面是內部類node:
static class nodeimplements map.entry
public final k getkey()
public final v getvalue()
public final string tostring()
public final int hashcode()
public final v setvalue(v newvalue)
public final boolean equals(object o)
return false;}}
可以看到,是乙個很常見的節點的表達方式,下面這個圖就沒有寫hash,因為hash使用制定存放位址的,這裡的next一般是為了解決雜湊衝突而設定的,本篇文章下面還有一幅圖更詳細
新建hashmap物件後,只有使用它,它才會初始化,也就是put語句,使用put後
final v putval(int hash, k key, v value, boolean onlyifabsent,
boolean evict)
所以由於table為空,所以初始化也就是執行resize方法,tab = resize();呼叫了resize()方法
繼續向下看:
final node resize()
else if ((newcap = oldcap << 1) < maximum_capacity &&
oldcap >= default_initial_capacity)
newthr = oldthr << 1; // double threshold
}@pass
else if (oldthr > 0) // initial capacity was placed in threshold
newcap = oldthr;
else
@pass
if (newthr == 0)
threshold = newthr;
//threshold初始化了
//開始新建乙個node陣列,大小為newcap
node newtab = (node)new node[newcap];
//table賦予值
table = newtab;
@pass
//下面**也被省略
return newtab;
}
目前就完成了初始化,得到乙個預設容量的鍊錶,然後繼續執行putval方法
final v putval(int hash, k key, v value, boolean onlyifabsent, boolean evict)
//...也省略
return null;
}
// create a regular (non-tree) node
nodenewnode(int hash, k key, v value, nodenext)
可以看到他是建立節點的函式,繼續呼叫node的構造方法,上面已經介紹了node和它的構造方法,所以返回了乙個新的節點,由於這是第乙個節點,也就是頭節點。繼續新增節點和上面步驟一樣,不過需要注意的是,當遇到hash衝突時,也就是我們要存放乙個元素,根據其hash值存放,不過檢測到原節點陣列該位置已經有元素,並且他們兩個的key值不一樣,這就遇到了hash衝突,所以我們會執行雜湊桶,也就是鏈位址法去解決衝突,如果不了解雜湊桶,可以參見我另一篇文章;
下面我介紹一下雜湊衝突元素的新增:(從第乙個雜湊衝突介紹)
final v putval(int hash, k key, v value, boolean onlyifabsent,
boolean evict)
}//執行
v oldvalue = e.value;
if (!onlyifabsent || oldvalue == null)
e.value = value;
afternodeaccess(e);
return oldvalue;}}
++modcount;
if (++size > threshold)
resize();
afternodeinsertion(evict);
return null;
}
此圖就講解了hash衝突的解決方案。如果雜湊桶中元素過多會使用樹去代替鍊錶,樹在hashmap中是很重要的乙個結構,足足佔了600行**。以後會專門講解。
HashMap原始碼分析 一
還是從我們使用者的角度一步一步來分析吧。首先我們一般 map map new hashmap 構造方法原始碼如下。其實只是初始化了乙個裝載因子,這個變數幹啥用的呢?loadfactor譯為裝載因子。裝載因子用來衡量hashmap滿的程度。loadfactor的預設值為0.75f。計算hashmap的...
逐行分析jQuery原始碼
注意 本次原始碼分析選擇2.0.3 因為不支援ie6 7 8,就少了很多相容的hack的寫法,對了解jquery的實現原理有很大的幫助 1.jquery有不同的版本,從2.x版本便不再支援ie6 7 8 將jquery拆分長框架一點一點進行了解 2.function 這個叫匿名函式自執行 3.匿名函...
HashMap原始碼分析
public hashmap int initialcapacity,float loadfactor 2 接下來是重要的put方法,put方法用於將鍵值對儲存到map中,讓我們來具體分析一下。public v put k key,v value if key null 若key為null,則將va...