深入探究HashMap.put方法實現細節

在Java中,HashMap是應用最廣泛的數據結構之一,它提供了一種基於鍵值對(key-value)的存儲方式,可以快速地存取、刪除和檢索數據。其中,put方法是HashMap中最主要的方法之一,本文將從多個方面深入探究HashMap.put方法實現細節。

一、put方法的使用

在Java中,使用put方法將數據放入HashMap中,具體使用方式如下:

HashMap map = new HashMap();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);

以上代碼將三個鍵值對放入了HashMap中,即{“A”:1, “B”:2, “C”:3}。通過這種方式,就可以在HashMap中快速地存儲和查找數據了。

二、put方法的實現

HashMap的底層實現是基於數組和鏈表(或紅黑樹)的,存儲數據的時候,HashMap首先根據key的hashCode值來計算其在數組中的位置,然後將該位置上的數組元素作為鏈表頭,如果鏈表頭還沒有存儲過key-value,那麼直接放入,否則需要遍歷鏈表,找到最後一個元素後將其next指向新存儲的元素。

下面是HashMap中put方法的重要代碼實現:

public V put(K key, V value) {
    if (table == EMPTY_TABLE) {
        inflateTable(threshold);
    }
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    for (Entry e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }
    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

在上面的代碼中,如果table數組還沒有初始化,需要先進行初始化。然後,根據key的hashCode值和table數組的長度,計算其在數組中的位置。接着,遍歷在該位置上的鏈表,如果找到了相同的key-value,則更新value值並返回舊值;如果沒有找到,則將新的key-value插入到鏈表的末尾。

三、關於hash方法

在put方法的實現中,需要先調用hash方法計算key的hashCode值。下面是HashMap中hash方法的代碼實現:

final int hash(Object k) {
    int h = hashSeed;
    if (0 != h && k instanceof String) {
        return sun.misc.Hashing.stringHash32((String) k);
    }
    h ^= k.hashCode();
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

在上面的代碼中,先獲取hashSeed的值,如果該值不為0且key是String類型,就調用sun.misc.Hashing.stringHash32方法來計算hashCode值;否則,直接使用key的hashCode值。

為什麼要進行h ^= (h >>> 20) ^ (h >>> 12)和h ^= (h >>> 7) ^ (h >>> 4)操作呢?這是為了使hashCode更加分散,從而減少哈希衝突的概率。上述操作使用了位運算,可以大幅提高計算效率。

四、關於擴容

當HashMap中元素數量達到了threshold(容量*負載因子)時,就會自動進行擴容操作。擴容實際上就是創建一個更大的table數組,然後將原來的元素重新分配到新數組中。下面是HashMap中resize方法的代碼實現:

void resize(int newCapacity) {
    Entry[] oldTable = table;
    int oldCapacity = oldTable.length;
    if (oldCapacity == MAXIMUM_CAPACITY) {
        threshold = Integer.MAX_VALUE;
        return;
    }
    Entry[] newTable = new Entry[newCapacity];
    transfer(newTable, initHashSeedAsNeeded(newCapacity));
    table = newTable;
    threshold = (int)(newCapacity * loadFactor);
}

在代碼中,首先獲取原table數組的長度,然後判斷是否達到了最大容量(2的30次方)。如果已達到最大容量,則不再進行擴容。否則,創建一個新的Entry數組,調用transfer方法將原table數組中的元素重新分配到新數組中。最後將table指向新數組,同時更新threshold的值。

五、關於線程安全

HashMap並不是線程安全的,即如果多個線程同時對同一個HashMap進行操作,可能會出現不一致的結果。因此,在並發環境下應該使用ConcurrentHashMap來替代HashMap,後者是線程安全的。

六、小結

通過以上分析,我們深入探究了HashMap.put方法的實現細節。在使用HashMap的過程中,尤其要注意hash方法和擴容的相關實現,同時要在並發場景下使用線程安全的ConcurrentHashMap。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/242169.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:47
下一篇 2024-12-12 12:47

相關推薦

  • int類型變量的細節與注意事項

    本文將從 int 類型變量的定義、聲明、初始化、範圍、運算和類型轉換等方面,對 int 類型變量進行詳細闡述和講解,幫助讀者更好地掌握和應用 int 變量。 一、定義與聲明 int…

    編程 2025-04-29
  • 解決.net 6.0運行閃退的方法

    如果你正在使用.net 6.0開發應用程序,可能會遇到程序閃退的情況。這篇文章將從多個方面為你解決這個問題。 一、代碼問題 代碼問題是導致.net 6.0程序閃退的主要原因之一。首…

    編程 2025-04-29
  • ArcGIS更改標註位置為中心的方法

    本篇文章將從多個方面詳細闡述如何在ArcGIS中更改標註位置為中心。讓我們一步步來看。 一、禁止標註智能調整 在ArcMap中設置標註智能調整可以自動將標註位置調整到最佳顯示位置。…

    編程 2025-04-29
  • Python中init方法的作用及使用方法

    Python中的init方法是一個類的構造函數,在創建對象時被調用。在本篇文章中,我們將從多個方面詳細討論init方法的作用,使用方法以及注意點。 一、定義init方法 在Pyth…

    編程 2025-04-29
  • Python創建分配內存的方法

    在python中,我們常常需要創建並分配內存來存儲數據。不同的類型和數據結構可能需要不同的方法來分配內存。本文將從多個方面介紹Python創建分配內存的方法,包括列表、元組、字典、…

    編程 2025-04-29
  • 用不同的方法求素數

    素數是指只能被1和自身整除的正整數,如2、3、5、7、11、13等。素數在密碼學、計算機科學、數學、物理等領域都有着廣泛的應用。本文將介紹幾種常見的求素數的方法,包括暴力枚舉法、埃…

    編程 2025-04-29
  • Python中讀入csv文件數據的方法用法介紹

    csv是一種常見的數據格式,通常用於存儲小型數據集。Python作為一種廣泛流行的編程語言,內置了許多操作csv文件的庫。本文將從多個方面詳細介紹Python讀入csv文件的方法。…

    編程 2025-04-29
  • 使用Vue實現前端AES加密並輸出為十六進制的方法

    在前端開發中,數據傳輸的安全性問題十分重要,其中一種保護數據安全的方式是加密。本文將會介紹如何使用Vue框架實現前端AES加密並將加密結果輸出為十六進制。 一、AES加密介紹 AE…

    編程 2025-04-29
  • Python學習筆記:去除字符串最後一個字符的方法

    本文將從多個方面詳細闡述如何通過Python去除字符串最後一個字符,包括使用切片、pop()、刪除、替換等方法來實現。 一、字符串切片 在Python中,可以通過字符串切片的方式來…

    編程 2025-04-29
  • 用法介紹Python集合update方法

    Python集合(set)update()方法是Python的一種集合操作方法,用於將多個集合合併為一個集合。本篇文章將從以下幾個方面進行詳細闡述: 一、參數的含義和用法 Pyth…

    編程 2025-04-29

發表回復

登錄後才能評論