歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> HashMap的存取解析

HashMap的存取解析

日期:2017/3/1 9:17:00   编辑:Linux編程

今天想了解點HashMap的存取解析。大家都知道HashMap是鍵值對存在的,key-value的形式。但,內部是怎麼存儲的?我們一起來看看吧

標注:基於的jdk版本為1.6.0_45

First,大家都知道Map的entrySet方法返回的是Set<Entry>,所以就好奇Entry到底是個什麼東西?

Entry是接口,是Map接口中的一個內部接口,Map提供的接口就不給大家介紹了,Entry提供的接口方法有:

K getKey() //獲取Entry的key值

V getValue() //獲取Entry的value值

setValue(V value) //替換value值

equals(Object o)//你懂的

hashCode() //你也懂的

其實這些方法大家也不陌生 微笑

Second,HashMap.Entry實現Map.Entry接口?

看代碼,我們發現HashMap.Entry是一個Link結構,並且key和value為其屬性,並使用next指向下一個Entry。

關於方法的實現就不介紹了,HashMap額外提供了兩個空方法,一個是recordAccess,一個是recordRemoval,在HashMap的介紹中,不多做介紹,在後面的LinkedHashMap再詳細說明

Third,HashMap怎麼利用Entry存放key-Value呢?並且,HashMap是怎麼遍歷的呢?是對Entry的Link遍歷?有了這一連串的疑問之後,繼續探索吧!

HashMap使用Entry數組,如下圖1:

上圖中transient修飾符是啥意思呢?

是一個臨時非序列化的變量,不可以被序列化存放起來。生命周期僅存於內存中。

Third_First:存放

HashMap提供的put方法執行操作,請注意putForNullKey和put的方法類似,只是putForNullKey定好了table的存放位置:

1.獲取key的hash。其中的hash方法只是為了保證它有唯一的值,並且null的hash一定是0.

2.在圖1中的table中找到key對應的位置使用的方式 hash & length,確定index

3.在table[i]存放的Entry對象中繼續遍歷,看其中是否存在hash、key是否完全一樣的,如果是則直接替換

4.如果步驟3找不到完全匹配的,則直接在table[i]對應的地方最後一個鏈表節點增加該元素

addEntry的處理:1.取到index的Entry;2.重新給一個新的鏈接,鏈接的是最新放入的,完全符合隊列link;3.長度超過設定擴展至兩倍

Third_Second:遍歷

其中用內部類HashIterator處理的,設定一個next Entry和current Entry。next為下一個點,current是當前點。咱們使用的Iterator.next接口具體實現方法為HashIterator的nextEntry。nextEntry方法中1.是對Entry鏈進行遍歷,如果到這個鏈的隊尾,則從table中取得下一個Entry鏈。2.將之前查找到的Entry返回給前台。源碼如下:

一位姓丁的NB同事曾經排查過一個高並發的情況下:HashMap如果EntryA的next指向EntryB,而EntryB的next指向EntryA,會導致get死循環。

Copyright © Linux教程網 All Rights Reserved