一.Put方法
情況一:
- 點擊上面put進入下面
第一步:先取得hashCode值;
第二步:根據hashCode值取得hash值;
第三步:hash值取余得到一個下標i;
以上代碼如下:
結果如下:
第四步:遍歷下標位置的hash桶;
第五步:如果引用相等或equals相等,做一個替換;
2.點擊上面hash進入下面
3.下面map = null;打斷點
4.打完斷點進入下面,發現key=”a10”,緊接着next下面key=”a0”,所以a10和a0儲存在第【6】個位置。
一.Put
情況二:
1.
2.上述點擊put進入下面底層代碼
上述u1=null,上面藍色部分不執行;
如果值沒存過,放到addEntry(hash,key,value,i)里面存,返回null;
如果值存過做if判斷,hashCode值相等而且引用相等或者equals相等,值相等才能發生替換返回oldValue;
注意:點擊上面e.recordAccess(this)進入下面:把舊的值放到新的value里面,把新的里面next引用去指向那個舊的值。
注意:點擊上上面addEntry(hash,key,value,i);進入下面,當size>=threshold時,求出hash值,下面2*table.length擴容兩倍后重新求出索引。
點擊上面createEntry(hash,key,value,bucketIndex)進入下面
把e取出來(代表舊的),new新的構造方法的時候把舊的給傳進去(里面key和value是新的),點擊上面Entry方法進入下面
上面讓next = n表示next引用去指向舊的,這樣就形成一個鏈表(通過hash碰撞才能實現鏈表)。
二.get方法
get是反過來操作一遍,根據key再求hash,根據hash再余運算獲取hash桶的下標,hash值遍歷不為空的值時,判斷如果查到索引i(或者查到里面鏈表e.next),並且查到相應索引值和鍵值,則返回一個值,如下:
上面如果第一個元素key為null,直接取第一個元素,否則點擊getEntry()方法把key傳進去,判斷size是否等於0,Entry()對象里面有next引用,next引用會指向另一個Entry()對象,所有用了for取遍歷取出來的Entry,if判斷hash值是否相等。
hashMap原理:
總結:1.HashMap底層是數組加鏈表,之所以用數組因為數組內存空間是連續的,用鏈表是因為插入和刪除比較快的,只需要一個引用對象去指向另一個引用對象;
2.用map底層只需解釋put方法,put一個新的k和value值的時候*(如果key為null放在hash表的第一個位置,如果不為null對key求hash,對key的值和hash表的長度做余運算去獲取keyvalue鍵值對,hash位置有元素判斷是否有hash碰撞,把舊的取出來,把新的放到舊的位置上,把新的應用對象里面的next去指向那個舊的oldvalue,這樣形成一個列表關系),這個列表就形成了;至於怎么添加則要調用Entry方法,先去判斷當前hash表的容量是否足以容納當前要存放的這些元素,如果不足以容納則要對hash表進行擴容2(n)(擴容效率低,最大2(30))對keyhash重新去求hash ,重新獲取hash表的下標,再調用ENtry方法,然后完成這個存儲的過程;
3.get方法是反過來操作一遍,根據key再求hash,根據hash再余運算獲取hash桶的下標,根據下標遍歷求出對應Entry的鏈表,遍歷出列表取出來想要的那個key。具體:如果第一個元素key為null,直接取第一個元素,否則點擊getEntry()方法把key傳進去,判斷size是否等於0,Entry()對象里面有next引用,next引用會指向另一個Entry()對象,所有用了for取遍歷取出來的Entry,if判斷hash值是否相等。
hashMap與HashTable的區別:
- map線程不安全;初始化容量16;鍵值對可以為空;性能高;位運算符;最大擴容2(30);
- table線程安全;初始化容量11;鍵值對不能為空;