這幾天跳槽 被人問得最多的問題就是基礎方面的知識..當時學習的時候有點囫圇吞棗..現在回頭把這些基本的集合類原始碼都仔細閱讀下
hashmap 用的是最頻繁的.. 所以問得也最多了.
initcapacity 初始化的容量
loadfacotr 負載因子 主要用來計算threshold的值
threshold 閥值
這幾個關鍵屬性主要在建構函式中賦值.. 受影響的地方是resize方法..
// 這個預設的建構函式
public hashmap()
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;}}
v oldvalue = e.value;
if (!onlyifabsent || oldvalue == null)
e.value = value;
afternodeaccess(e);
return oldvalue;}}
++modcount;
if (++size > threshold)
resize();
afternodeinsertion(evict);
return null;
}
主要流程如下 如有偏差請指正
大體如上面的流程 有幾個老會被問的點.. 乙個是如何取下標.. 乙個是resize如何rehash
1 是如何計算下標的.. **中使用的是 (n-1) & hash n是table.length 其實就是取模..當然n要是2的冪
因為 n是2的冪 則說明 n的二進位制只有乙個數是1 其他都是0 n-1的話 那就是有(加入n=2^x) 則有 x個1.. 任意數字y與x個1與運算結果是x個1範圍內的1.. 超出x位的都是0 與後也是0
n-100000000 0 0
111111
hash
11111111 11
101011
取與的話其實只要關注紅色位置的與結果 其他位置因為n-1都是0 所以結果也是0
00000000 00 101011 結果就是這麼多了.. 綠色的部分其實就是n的倍數嘛.. 這樣把倍數全部去掉剩下的就是餘數了。
2 在resize 中也有對應的操作
在resize 的時候需要將老陣列中的元素都移到新的陣列中.. 這個時候就需要重新計算元素的位置..
resize中的實現是 hash & n n是 oldtable.length; 如果是 1 則需要移動到新的位置上面 新的位置是index+n
如果是0 則不需要移動位置... index 還是原來的位置...為什麼呢..
因為我們在擴容的時候是按一倍類擴容的.. 那計算index的時候則是
2n-1
00000000 01
111111
hash
11111111 11
101011 rs
00000000 01
101011 n
00000000 01
000000
這個時候我們其實只需要比較 第7個1與上我們的hash對應的第7個1 是否是1 剛好第幾個1就是oldtab.lengh的值
因為我們只需要乙個位置的結果則用n與上hash 就可以了。
final node resize()
// 沒超過最大值,就擴充為原來的2倍
else if ((newcap = oldcap << 1) < maximum_capacity &&
oldcap >= default_initial_capacity)
newthr = oldthr << 1; // double threshold
}else if (oldthr > 0) // initial capacity was placed in threshold
newcap = oldthr;
else
// 這裡傳遞了initcapactiy 則會跑到這裡來.. 還有就是擴充了幾次然後沒有超過
// default_initial_capacity的時候也會來這裡
if (newthr == 0)
threshold = newthr;
@suppresswarnings()
node newtab = (node)new node[newcap];
table = newtab;
if (oldtab != null)
// 原索引+oldcap
else
} while ((e = next) != null);
// 原索引放到newtable裡
if (lotail != null)
// 原索引+oldcap放到newtable裡
if (hitail != null) }}
}}return newtab;
}
3 hash中的紅黑樹.. 還是有點沒有徹底掌握 HashMap原始碼解析
以jdk1.8為例,hashmap是乙個用於儲存key value鍵值對的集合,每乙個鍵值對是乙個node jdk1.7叫做entry 後台是用乙個node陣列來存放資料,這個node陣列就是hashmap的主幹。這裡我們主要來分析hashmap的get和put方法。public v put k k...
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 ...
Hashmap原始碼解析
話不多說,直接看hashmap的put 方法原始碼 這是jdk1.8的原始碼 與1.7有所不同。final v putval int hash,k key,v value,boolean onlyifabsent,boolean evict if e.hash hash k e.key key ke...