分析源碼:android-28
Map:接口
HashMap是個(gè)散列鏈表萎庭。
put方法實(shí)現(xiàn)
HashMap在put的時(shí)候,先根據(jù)key的hashCode重新計(jì)算hash值忌傻。
根據(jù)hash值判斷要存放在鏈表數(shù)組的位置
Node<K,V> p = tab[i = (n - 1) & hash]
如果要存放的位置為null屁置,則直接放置到該位置。
如果不為空朗若,需要判斷
兩個(gè)Node的hash值和key值是否相等恼五,如果相等,則直接覆蓋
如果不相等哭懈,則插入到該位置鏈表的表尾(不同版本的代碼可能不同灾馒,之前的版本是插入到鏈表的表頭)
如果鏈表過長,超過8之后遣总,會(huì)轉(zhuǎn)換成紅黑樹(暫時(shí)先略過睬罗,以后在研究)
由此可以得到HashMap注定不是一個(gè)有序的結(jié)構(gòu)
對于相同hash值,采用鏈表的形式存放旭斥,一定程度上容达,解決了hash沖突問題
get方法實(shí)現(xiàn)
get(Object key)方法,也是用相同的方法獲取hash值垂券,找到該hash值對應(yīng)的位置花盐,并做出相應(yīng)的判斷
如果對應(yīng)位置的Node<K,V>為空,則直接返回null
如果有值
先取出first的node菇爪,并判斷key值是否等于我們傳入的key值卒暂,如果相等則返回
如果第一個(gè)不是我們需要的,就會(huì)一直按順序往下查找娄帖,直到找到或者鏈表結(jié)束返回null
resize擴(kuò)容
我平時(shí)習(xí)慣這樣寫
Map<String, Object> map = new HashMap<>();
所以先以這種形式來分析擴(kuò)容的情況
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
不帶參數(shù)的構(gòu)造函數(shù)也祠,沒有定義threshold(閾值)此時(shí) threshold=0
當(dāng)put一個(gè)鍵值對的時(shí)候,就是觸發(fā)擴(kuò)容操作
if (++size > threshold)
resize();
重點(diǎn)來了=佟U┖佟!削葱!
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
// MAXIMUM_CAPACITY 為 1 << 30 2的30次方
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
// 以第一次put為例奖亚,容量<< 1 擴(kuò)大為原來的2倍 此時(shí)oldCap為1, 則newCap為2 DEFAULT_INITIAL_CAPACITY = 16
// 條件不符合
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
//如果之前的容量超過16析砸,則閾值直接設(shè)置為原來的2倍
newThr = oldThr << 1; // double threshold
}
else if (oldThr > 0) // initial capacity was placed in threshold
newCap = oldThr;
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
// 以上條件不符合直接運(yùn)行到這
if (newThr == 0) {
// loadFactor 默認(rèn)為0.75 newCap=2
float ft = (float)newCap * loadFactor;
// 得到新的閾值 如果newCap < MAXIMUM_CAPACITY 為ture 則值為后面的結(jié)果昔字,如果為false則值為0
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float) MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
// 賦值 閾值更新為 =(int)裝載因子*新的容量大小
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
if (oldTab != null) {
// 將之前的轉(zhuǎn)移到新的
。。作郭。
}
return newTab;
}