hashMap 不用多說,你們確定都用過,今天我就hashMap的底層數據結構跟你們作一個分享。html
hashMap 是基於哈希表的 Map 接口的實現,以key-value的形式存在。在HashMap中,key-value老是會當作一個總體來處理,系統會根據hash算法來來計算key-value的存儲位置,咱們老是能夠經過key快速地存、取value。HashMap實現了Map接口,繼承AbstractMap。其中Map接口定義了鍵映射到值的規則,而AbstractMap類提供 Map 接口的骨幹實現,以最大限度地減小實現此接口所需的工做。java
hashMap中提供了3個構造方法,分別是:HashMap();HashMap(int initialCapacity);HashMap(int initialCapacity, float loadFactor)。這裏面主要涉及到2個參數,分別是:initialCapacity(初始容量,默認爲16)和loadFactor(加載因子,默認爲0.75),舉個例子你們就明白了。好比說我如今新建立一個hashMap,算法
Map map = new HashMap<String,Object>(16,0.75F);其中16表示該hashMap在初始化時的最大容量,或者說是哈希表中桶的數量,16*0.75=12表示該hashMap存儲鍵值對的最大數量,
當map中繼續put使鍵值對的數量大於12時,該map將會進行擴容的操做每次新建一個HashMap時,都會初始化一個table數組。table數組的元素爲Entry節點。
static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next; int hash; }
其中Entry爲HashMap的內部類,它包含了鍵key、值value、下一個節點next,以及hash值,這是很是重要的,正是因爲Entry才構成了table數組的項爲鏈表(也就是java經過鏈地址法解決hashMap的hash衝突問題)。hash在進行put的時候,執行步驟以下: 首先判斷key值是否爲空,若爲空,則調用putForNullKey方法(hashMap是支持key爲null的),若不爲空,則經過key來計算hash值,int hashCode = key.hashCode();再經過hashCode值計算該value存儲在數組中的位置座標index,計算方法爲hashCode%size,size爲該數組的長度;若是table數組在該位置處有元素,則經過比較是否存在相同的key,若存在則覆蓋原來key的value,不然將該元素保存在鏈頭(最早保存的元素放在鏈尾)。若table在該處沒有元素,則直接保存。數組
hashMap在取出鍵值對的時候步驟大體和上面的差很少,只是在數組上該值存在於一個鏈表中的時候,要對鏈表進行遍歷,經過equals()方法找到正確的value值。數據結構
補充說明一下:在java8.0之後,hashMap在存儲結構上作了必定優化,主要是在鏈表的長度達到8的時候,會將鏈表轉化成紅黑樹的方式存儲,這是由於鏈表在長度比較長的時候進行遍歷性能不是太好,而改用紅黑樹的數據結構能大大增長對數據的增刪給查的效率,提升hashMap的性能。函數
HashMap的底層數組長度老是2的n次方,在構造函數中存在:initialCapacity<<= 1;這樣作老是可以保證HashMap的底層數組長度爲2的n次方。當length爲2的n次方時,h&(length - 1)就至關於對length取模,並且速度比直接取模快得多,這是HashMap在速度上的一個優化。具體緣由能夠參考博客:https://www.cnblogs.com/dassmeta/p/5338955.html性能