hashMap怎麽保證hash一致性的
查看哈希碼百科:
哈希表可以說就是數組鏈表,底層還是數組但是這個數組每一項就是一個鏈表
一:為什麽說hashmap的put方法是根據key進行hashcode計算的呢?
查看源碼:
在查看hash方法,如下:
查看putVal方法:
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node [] tab; Node p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode )p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
二:hashmap怎麽解決key的hash值沖突問題的?
上圖是源碼截圖,說明:
1:初始化map的大小。默認是16
示例代碼:HashMap map = new HashMap();
2:如果tab為空,就newNode一個放到鏈表中
示例代碼:map.put("aa",1); 也就是圖-1測試代碼中的1
3:根據key算出的hash值如果存在,且key的值和map中已經存在的值equals了。所以就不處理。
如下圖:
測試代碼如圖-1測試代碼中的1和 2
4:如果p是TreeNode的子類進行putTreeValu
5:如果key的hash值和map中已經存在的key的hash相等且key不同的時候,如果數組該位置上沒有元素,就直接將該元素放到此數組中的該位置上。
如圖-1測試代碼 1和4中key的hesh值都為3104
圖-1測試代碼
在來看下Node這個內部類:
三:在來看看怎麽get方法
說明:
1:如果鏈表中第一個值的hash值和需要獲取的key的hash值相等的話,就直接取出。
2:如果鏈表first.next !=null就循環查找鏈表中的key,知道查詢到key.equals(k) 取出對應的值。
查看源碼或許感覺不懂,那麽畫圖來說明:
總結:
數據結構:哈希表可以說就是數組鏈表,底層還是數組但是這個數組每一項就是一個鏈表。
map的put方法:
1:new hashMap的時候初始化默認大小為16
2:當map.put("aa",1)的時候判斷map沒有值,就把aa算的hash值放到0X004的位置
3:當再次執行map.put("aa",1)的是計算aa的hash值為3104.此時在OX004的位置已經有數據了。進行判斷存在的key和新put的key是否相同。相同不處理,值覆蓋
4:執行map.put("aa",2)的時候key和已經存在的key相同就直接覆蓋value了
5:執行map.put(3104,"cc")的時候,key的hash值也為3104.此時數組中OX004已經存在數據,判斷key是否相同。發現3104和aa不相同【註:此時就發生了hash沖突】,那麽就aa這個鏈表前面追加3104
6:執行map.put("bb","cc")。假設bb計算出的hash值是3105就存放在了OX005上。
其他依次類推
map的get方法:
當執行map.get("bb")的時候先計算出bb的hash值為3105在對應的位置(也就是0X005)取出第一個判斷值是不是bb如果是就直接取出value.
當執行map.get("aa")的時候先計算出aa的hash值為3104,去對應的位置取出判斷值(3104)不等於(aa)且還有next。就循環取出進行比較。
hashMap怎麽保證hash一致性的