1.HashMap的概述數組
HashMap是map接口的實現,是線程非同步的。語序key爲null,而且順序是會變的。數據結構
HashMap的數據結構性能
HashMap其實是一個數組和鏈表的結合體,簡稱鏈表散列。spa
從圖中能夠看出,HashMap是一個數組結構,而每一個數組中的元素又是一個鏈表線程
Entry<,> Map.Entry<,> { ; ; Entry<,> ; ;
每一個Entry指向下一個元素的引用,然而爲何數組中的每一個元素是一個鏈表呢?由於HashMapcode
若是數組該位置上已經存放有其餘元素了,那麼在這個位置上的元素將以鏈表的形式存放,新加入的放在鏈頭,最早加入的放在鏈尾。若是數組該位置上沒有元素,就直接將該元素放到此數組中的該位置上。索引
3.HashMap中的方法
接口
put(key, value) { (key == ) putForNullKey(value); hash = (key.hashCode()); i = (hash, .); (Entry<,> e = [i]; e != ; e = e.) { Object k; (e.== hash && ((k = e.) == key || key.equals(k))) { oldValue = e.; e.= value; e.recordAccess(); oldValue; } } ++; addEntry(hash, key, value, i); ; }
這個方法主要是在添加一個元素,首先判斷key是否爲空,ci
當key爲null時,調用putForNullKey方法,將value放置在數組第一個位置。get
當key不爲空時,經過key的hashcode計算hash值,搜索指定hash值在對應table中的索引,判斷是否爲null,爲null則添加到索引處。
addEntry(hash, key, value, bucketIndex) { Entry<,> e = [bucketIndex]; [bucketIndex] = Entry<,>(hash, key, value, e); (++ >= ) resize(* .); }
addEntry(hash, key, value, i)方法根據計算出的hash值,將key-value對放在數組table的i索引處。
get(Object key) { (key == ) getForNullKey(); hash = (key.hashCode()); (Entry<,> e = [(hash, .)]; e != ; e = e.) { Object k; (e.== hash && ((k = e.) == key || key.equals(k))) e.; } ; }
理解put方法後,get方法其實就好理解了。反之便可,這裏再也不重複。
4. HashMap的resize(rehash):
當HashMap中的元素愈來愈多的時候,hash衝突的概率也就愈來愈高,由於數組的長度是固定的。因此爲了提升查詢的效率,就要對HashMap的數組進行擴容,數組擴容這個操做也會出如今ArrayList中,這是一個經常使用的操做,而在HashMap數組擴容以後,最消耗性能的點就出現了:原數組中的數據必須從新計算其在新數組中的位置,並放進去,這就是resize。
那麼HashMap何時進行擴容呢?當HashMap中的元素個數超過數組大小*loadFactor時,就會進行數組擴容,loadFactor的默認值爲0.75,這是一個折中的取值。也就是說,默認狀況下,數組大小爲16,那麼當HashMap中元素個數超過16*0.75=12的時候,就把數組的大小擴展爲 2*16=32,即擴大一倍,而後從新計算每一個元素在數組中的位置,而這是一個很是消耗性能的操做,因此若是咱們已經預知HashMap中元素的個數,那麼預設元素的個數可以有效的提升HashMap的性能。
5. HashMap的性能參數:
HashMap 包含以下幾個構造器:
HashMap():構建一個初始容量爲 16,負載因子爲 0.75 的 HashMap。
HashMap(int initialCapacity):構建一個初始容量爲 initialCapacity,負載因子爲 0.75 的 HashMap。
HashMap(int initialCapacity, float loadFactor):以指定初始容量、指定的負載因子建立一個 HashMap。
HashMap的基礎構造器HashMap(int initialCapacity, float loadFactor)帶有兩個參數,它們是初始容量initialCapacity和加載因子loadFactor。
initialCapacity:HashMap的最大容量,即爲底層數組的長度。
loadFactor:負載因子loadFactor定義爲:散列表的實際元素數目(n)/ 散列表的容量(m)。
負載因子衡量的是一個散列表的空間的使用程度,負載因子越大表示散列表的裝填程度越高,反之愈小。對於使用鏈表法的散列表來講,查找一個元素的平均時間是O(1+a),所以若是負載因子越大,對空間的利用更充分,然然後果是查找效率的下降;若是負載因子過小,那麼散列表的數據將過於稀疏,對空間形成嚴重浪費。
HashMap的實現中,經過threshold字段來判斷HashMap的最大容量: