Java HashMap實現原理詳解

HashMap是Java集合框架中常見的一種數據結構,它提供了快速存儲、查找和刪除元素的能力。它是由數組和鏈表實現的鍵值對,通過哈希演算法來快速定位數組下標,避免了遍歷整個數組來查找元素的低效率問題。

一、HashMap基本概念

在了解HashMap的實現原理之前,需要掌握HashMap的基本概念。

1. HashMap的鍵值對

HashMap的元素由鍵和值組成,稱為鍵值對。HashMap中的鍵和值必須都是對象才能被存儲。通常使用String作為鍵。

2. 哈希演算法

哈希演算法是通過將任意長度的數據映射為固定長度的數據,通常是一個較小的整數值,稱為哈希值。哈希值可以快速地用於查找數組或其他數據結構中的數據,提高數據的訪問效率。

3. 鍵的唯一性

HashMap中的鍵是唯一的。如果向HashMap中添加元素時,鍵已經存在,那麼該元素的值將會覆蓋掉原有的值。如果元素的值為null,則鍵可以重複。

二、HashMap的實現原理

HashMap是由數組和鏈表組成的鍵值對,每個鍵值對稱為一個Entry對象。HashMap的核心就是通過哈希演算法,將鍵值對存儲到數組的不同位置中,然後通過鏈表將相同下標的元素串起來。

三、HashMap的put方法實現原理

put方法是HashMap中的核心操作,用於向HashMap中添加元素。其實現方式如下:

public V put(K key, V value) {
    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;
}

在這個put方法中,有三個變數需要了解:

1. hash:通過hashCode()方法計算的鍵的哈希值。

2. i:計算出的鍵值對將要存儲的位置。

3. table:數組,用於存儲鍵值對。

put方法實現的流程如下:

1. 判斷鍵是否為null,如果是,直接調用putForNullKey方法,將值保存到map中,然後返回值。

2. 通過hash方法計算鍵的哈希值,然後通過indexFor方法計算出在table數組中的位置。

3. 從table數組中取出對應位置的元素,並遍歷這個元素的鏈表,查找是否有相同key的元素。

4. 如果找到了相同key的元素,則將新的值賦給元素的value,並返回原有的value。

5. 如果在鏈表中沒有找到相同key的元素,則將新的值添加到鏈表的最前面。

四、HashMap的get方法實現原理

get方法是用於獲取HashMap中指定鍵的值。其實現方式如下:

public V get(Object key) {
    if (key == null)
        return getForNullKey();
    Entry entry = getEntry(key);
    return null == entry ? null : entry.getValue();
}

final Entry getEntry(Object key) {
    int hash = (key == null) ? 0 : hash(key);
    for (Entry e = table[indexFor(hash, table.length)];
        e != null;
        e = e.next) {
        Object k;
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
    }
    return null;
}

在這個get方法中,有三個變數需要了解:

1. hash:通過hashCode()方法計算的鍵的哈希值。

2. i:計算出的鍵值對在table數組中的位置。

3. table:數組,用於存儲鍵值對。

get方法實現的流程如下:

1. 如果鍵為null,則直接調用getForNullKey 方法獲取值。

2. 通過哈希演算法和indexFor方法查找元素在table數組中的位置。

3. 從table數組中取出對應位置的元素,並遍歷這個元素的鏈表,查找是否有相同的鍵,如果找到了,則返回對應的value。

4. 如果在鏈表中沒有找到相同key的元素,則返回null。

五、HashMap的容量和負載因子

HashMap的容量和負載因子是指table數組的長度和鍵值對個數之比。

當鍵值對的個數達到容量和負載因子的乘積時,就需要對table進行擴容。同時,在擴容時,需要將現有的元素重新哈希,然後存儲到新的table數組中。

在HashMap中,負載因子默認為0.75,即當鍵值對的個數達到75%的容量時,進行擴容。這是基於將數組長度設置為2的冪的演算法,確保哈希鏈表的最大長度為8位,從而提高了查找和插入元素的效率。

六、HashMap的使用場景

HashMap適用於需要快速查找、插入、刪除數據的場景。由於其底層是基於數組和鏈表實現的,因此處理大量數據時,執行效率較高。尤其是在需要頻繁遍曆元素的場景下,與傳統的數組和鏈表相比,其查找效率更高。

七、HashMap的例子

以下是一個簡單的HashMap例子,用於存儲人名和年齡:

public class HashMapExample {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Tom", 30);
        map.put("Jerry", 25);
        map.put("Mike", 28);
        map.put("Lucy", 33);

        System.out.println("Tom's age is " + map.get("Tom")); // Tom's age is 30

        map.remove("Lucy");

        System.out.println("Map contains Lucy? " + map.containsKey("Lucy")); // Map contains Lucy? false

        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " is " + entry.getValue() + " years old.");
        }
    }
}

在這個例子中,我們創建了一個HashMap對象,並將四對鍵值對(人名和年齡)保存到HashMap中。然後通過get方法獲取Tom的年齡,再使用remove方法刪除Lucy,最後使用entrySet方法遍歷Map的所有元素,並輸出人名和年齡。

八、總結

本文探討了HashMap的原理和實現方式。我們深入了解了HashMap的數據結構,介紹了其put方法和get方法的實現原理,還介紹了HashMap的容量、負載因子以及使用場景。

HashMap在Java中使用廣泛,它提供了快速存儲、查找和刪除元素的能力,避免了遍歷整個數組來查找元素的低效率問題。相信通過本文的介紹,讀者能夠更全面地了解HashMap,並在實際開發中更加靈活地使用HashMap。

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

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

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java Bean載入過程

    Java Bean載入過程涉及到類載入器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean載入的過程。 一、類載入器 類載入器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字元串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字元串中是否存在多個指定字元: 一、字元串遍歷 字元串是Java編程中非常重要的一種數據類型。要判斷字元串中是否存在多個指定字元…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29
  • Harris角點檢測演算法原理與實現

    本文將從多個方面對Harris角點檢測演算法進行詳細的闡述,包括演算法原理、實現步驟、代碼實現等。 一、Harris角點檢測演算法原理 Harris角點檢測演算法是一種經典的計算機視覺演算法…

    編程 2025-04-29

發表回復

登錄後才能評論