HashMap的研究

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的最大容量:

相關文章
相關標籤/搜索