Java中HashMap的實現原理

Java中的HashMap是一種非常常見的數據結構,可以在O(1)的時間複雜度下進行插入、查找、刪除等操作。本文將從多個方面對Java中HashMap的實現原理進行詳細的闡述。

一、HashMap的概述

HashMap是一種基於哈希表的數據結構,它將鍵映射到值。實現HashMap需要使用hashCode和equals方法,hashCode用於計算鍵的哈希值,equals方法用於比較鍵的值是否相等。HashMap將鍵的哈希值映射到數組的下標,將鍵和值存儲在數組中的相應位置。

HashMap允許null鍵和null值。HashMap不是同步的,因此在並發環境中的操作可能會引發線程安全問題。

下面是HashMap的代碼示例:


public class HashMap extends AbstractMap implements Map, Cloneable, Serializable {
    /* HashMap的內部實現 */
}

二、HashMap的主要屬性

HashMap的主要屬性包括:

– capacity:HashMap中的數組容量,默認值為16,必須是2的冪。
– loadFactor:HashMap的裝載因子,默認值為0.75,用於確定何時需要調整HashMap的容量。
– threshold:HashMap的閾值,表示當Hash表中元素個數超過該值,需要進行擴容操作。
– modCount:用於實現迭代器的快速失敗機制。

下面是HashMap的主要屬性的代碼示例:


public class HashMap extends AbstractMap implements Map, Cloneable, Serializable {
    /**
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The load factor used when none specified in constructor.
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * The bin count threshold for using a tree rather than list for a
     * bin.  Bins are converted to trees when adding an element to a
     * bin with at least this many nodes. The value must be greater
     * than 2 and should be at least 8 to mesh with assumptions in
     * tree removal about conversion back to plain bin. 
     */
    static final int TREEIFY_THRESHOLD = 8;

    /**
     * The bin count threshold for untreeifying a (split) bin during a
     * resize operation. Should be less than TREEIFY_THRESHOLD, and at
     * most 6 to mesh with shrinkage detection under removal.
     */
    static final int UNTREEIFY_THRESHOLD = 6;

    /**
     * The smallest table capacity for which bins may be treeified.
     * (Otherwise the table is resized if too many nodes in a bin.)
     * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
     * between resizing and treeification thresholds.
     */
    static final int MIN_TREEIFY_CAPACITY = 64;
    
    /* HashMap的內部實現 */
}

三、HashMap的哈希演算法

HashMap使用哈希演算法將鍵值對映射到數組的下標,HashMap使用的哈希演算法是JDK官方提供的哈希演算法,它將鍵的哈希值右移16位並且與原哈希值進行異或操作,然後將結果作為數組下標。

下面是HashMap的哈希演算法的代碼實例:


final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

四、HashMap的底層數據結構

HashMap的底層數據結構是一個數組和一個鏈表。數組的大小為2的n次方,鏈表用來解決哈希衝突。當多個鍵映射到數組的同一個下標時,HashMap會將這些鍵值對保存在同一個鏈表中。當鏈表長度達到8時,鏈表將被轉換為紅黑樹,這樣可以提高查找效率。

下面是HashMap的底層數據結構的代碼示例:


static class Node implements Map.Entry {
    final int hash;
    final K key;
    V value;
    Node next;

    Node(int hash, K key, V value, Node next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }

    public final K getKey()        { return key; }
    public final V getValue()      { return value; }
    public final String toString(){ return key + "=" + value; }

    public final int hashCode() {
        return Objects.hashCode(key) ^ Objects.hashCode(value);
    }

    public final V setValue(V newValue) {
        V oldValue = value;
        value = newValue;
        return oldValue;
    }

    public final boolean equals(Object o) {
        if (o == this)
            return true;
        if (o instanceof Map.Entry) {
            Map.Entry e = (Map.Entry)o;
            if (Objects.equals(key, e.getKey()) &&
                Objects.equals(value, e.getValue()))
                return true;
        }
        return false;
    }
}

五、HashMap的代碼示例

下面是一個簡單的HashMap的代碼示例,用於將學生的姓名和成績保存在HashMap中:


import java.util.HashMap;

public class TestHashMap {

    public static void main(String[] args) {

        HashMap<String, Integer> scores = new HashMap<>();
        scores.put("張三", 90);
        scores.put("李四", 80);
        scores.put("王五", 70);
        scores.put("趙六", 60);

        for (String name : scores.keySet()) {
            System.out.println(name + "的成績為:" + scores.get(name));
        }
    }
}

輸出結果為:

張三的成績為:90

李四的成績為:80

王五的成績為:70

趙六的成績為:60

六、HashMap的總結

通過本文的介紹,我們了解了Java中HashMap的實現原理,包括它的概述、屬性、哈希演算法、底層數據結構以及代碼示例。掌握了HashMap的實現原理,可以幫助我們更好地使用HashMap,在開發中更快地解決問題。

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

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

相關推薦

  • Java JsonPath 效率優化指南

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

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

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

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

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

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

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

    編程 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
  • Java 8 Group By 會影響排序嗎?

    是的,Java 8中的Group By會對排序產生影響。本文將從多個方面探討Group By對排序的影響。 一、Group By的概述 Group By是SQL中的一種常見操作,它…

    編程 2025-04-29

發表回復

登錄後才能評論