hashmap相關的問題

hashmap相關的問題

  1. hashmap源碼 https://blog.csdn.net/ooo123lll/article/details/81103234#335-get
  2. hashmap擴容、爲什麼是2n(2的n次方)擴容 https://www.cnblogs.com/williamjie/p/9358291.html
    擴容或者初始化容量時,都是以2的n次方擴容,這主要原因是,hashmap定位key的下標的機制決定的。根據源碼:
public V put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
    // 若“key不爲null”,則計算該key的哈希值,然後將其添加到該哈希值對應的鏈表中。
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        // 若“該key”對應的鍵值對已經存在,則用新的value取代舊的value。然後退出!
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    // 若“該key”對應的鍵值對不存在,則將“key-value”添加到table中
    modCount++;
    addEntry(hash, key, value, i);
    return null;
}
// 返回索引值
// h & (length-1)保證返回值的小於length
static int indexFor(int h, int length) {
        return h & (length-1);
}

我們可以看到當put或者get方法時,會先對key進行hashcode獲得hash值,然後用hash值和(table長度-1)進行與運算(indexFor方法),從而得到key的table數組的下標,其實除了與運算,還可以直接使用mod取餘運算(hash值%(table長度-1))來獲得下標位置,但由於在計算機中取餘運算很耗時(計組中有學二進制的除法運算會比二進制的直接與運算複雜很多),所以hashmap採用的是運算來定位key的下標。
如果table長度是2的n次方,那麼table.length-1的二進制一定是都是1,如length=16,則length-1=15 -> 1111
那麼任何一個小於table.length-1的數字跟length-1進行與運算都是它本身,如9->1001,1001 & 1111 = 1001;這樣能保證key的分步均勻,減少key的衝突。
但如果不是2的n次方,假設table.length=15,則table.length-1=14 -> 1110,key的hash值認爲9,即1001 & 1110 = 1000 ,發現了什麼?只要key的hash值的二進制位1的都不能 用了,這樣會跟原本應該在***0的位置的key產生衝突,然後hashmap使用的是拉鍊法解決衝突,所以衝突的key會放到鏈表中,無衝突的hashmap取值的時間複雜度爲O(1),如果衝突,則在鏈表中查詢當前值的時間複雜度爲O(n),這嚴重降低了hashmap的查詢料率。
所以不管是在初始化容量時還是在擴容時,jdk會自動幫你選擇以2den次方進行擴容。

  1. 負載因子爲什麼是0.75 https://www.cnblogs.com/peizhe123/p/5790252.html
    當創建 HashMap 時,有一個默認的負載因子(load factor),其默認值爲 0.75,這是時間和空間成本上一種折衷:增大負載因子可以減少 Hash 表(就是那個 Entry 數組)所佔用的內存空間,但會增加查詢數據的時間開銷,這是因爲增大負載因子,那麼key的衝突會增大,然後存儲到鏈表的節點,鏈表的節點查詢時間複雜度是O(n),而查詢是最頻繁的的操作(HashMap 的 get() 與 put() 方法都要用到查詢);減小負載因子會提高數據查詢的性能,但會增加 Hash 表所佔用的內存空間,負載因子越小,table數組的位置就越來被使用。

  2. hashMap爲什麼線程不安全(hash碰撞與擴容導致)https://www.cnblogs.com/qiumingcheng/p/5259892.html

  3. hashmap衝突的解決方法以及原理分析:https://www.cnblogs.com/peizhe123/p/5790252.html

  4. JDK1.8對HashMap有哪些優化 hashmaphttps://blog.csdn.net/hu199055/article/details/78717544

  5. 使用類自定義hashmap的key,要重寫哪些方法,hashcode方法和equals方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章