欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

HashMap中哈希值與數組坐標的關聯方式

 更新時間:2025年05月13日 10:11:39   作者:找不到、了  
這篇文章主要介紹了HashMap中哈希值與數組坐標的關聯方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

在 HashMap 中,通過對鍵的哈希值進行處理,能夠將生成的哈希碼映射到 HashMap 內部數組(桶)中的索引位置。

如下圖所示:

這一過程可以通過以下步驟認真分析:

想了解更多map數據結構更多的可參考:HashMap的擴容機制

1、哈希值的生成與處理

如我們之前討論的,第一次會調用 hashCode() 方法來生成一個完整的 32 位整數哈希碼。然后,使用以下代碼對哈希值進行處理:

int h = key.hashCode();
h ^= (h >>> 16);

2、計算桶的索引

經過處理后,哈希值可能會更分散,最后會用于計算桶的索引位置:

int index = h & (n - 1);

2.1 這里的計算方法:

  • n 是當前 HashMap 內部數組的長度(即桶的數量)。為了更高效地計算數組索引,我們通常選擇 n 為 2 的冪(例如 16、32、64 等),這允許高效的位操作。
  • n - 1 的計算是為了確保采用位與運算來進行取模操作。例如,如果 n 為 16(即 10000),那么 n - 1 為 15(即 01111)。這樣做的好處是通過位與運算能夠快速計算出在數組中的有效索引。

2.2 示例

假設生成的哈希值 h0b11010110110101101010011000111101(即 32 位二進制數),并且 HashMap 的桶數量 n 為 16(也即 index = h & 15)。

計算過程:

  • 二進制示例哈希值:11010110110101101010011000111101
  • n-100000000000000000000000000001111 (即 15 的二進制表示)

進行位與操作:

        11010110110101101010011000111101
  &     00000000000000000000000000001111
  ------------------------------------------
        00000000000000000000000000000101  (結果即為 index)
  • 結果 index 是 5,表示該鍵值對應的元素存放在 HashMap 的第 5 個桶(數組索引為 5 的位置)。

3、哈希值總結

  • 哈希值處理:通過對原始哈希碼的處理(即與高位信息進行異或),可以確保更均勻的哈希分布,從而減少碰撞的機會。
  • 桶的索引計算:使用 h & (n - 1) 技巧使得計算過程高效,將生成的哈希值直接映射到 HashMap 內部數組的有效索引,從而實現快速的鍵值對存儲和檢索。
  • 效率:以上步驟都是為了確保在 O(1) 平均情況下能快速訪問 HashMap 中的元素,同時減少由于哈希沖突引起的性能損失。

4、哈希沖突解決方案

拉鏈法(Separate Chaining)和開放尋址法(Open Addressing)是兩種常用的哈希表沖突解決策略。

它們在處理兩個或多個鍵沖突(即哈希函數返回相同索引)時采取不同的策略。

下面是對這兩種方法的詳細介紹及示例:

4.1. 拉鏈法(Separate Chaining)

1.原理

基本思路是為每個哈希表的桶(數組索引)維護一個鏈表(或其他數據結構),用來存儲所有哈希到同一索引位置的鍵值對。當發(fā)生沖突時,新的鍵值對會被追加到這個鏈表中。

2.特點

  • 沖突分離:拉鏈法可以有效處理沖突,因為每個桶可以容納多個元素。
  • 空間利用率:空間利用率較高,尤其在負載因子較大時。

3.示例

設想一個簡單的哈希表,哈希函數為 h(key) = key mod 5,并且存在以下鍵值對:

  • (3, "A")
  • (8, "B")
  • (13, "C")
  • (9, "D")

哈希表的桶數組將如下所示(使用鏈表處理沖突):

Index: 0  -> null
Index: 1  -> null
Index: 2  -> null
Index: 3  -> (3, "A") -> null
Index: 4  -> (8, "B") -> null

當插入鍵 13,計算得到 h(13) = 3,這個鍵會追加到索引 3 的鏈表中:

Index: 0  -> null
Index: 1  -> null
Index: 2  -> null
Index: 3  -> (3, "A") -> (13, "C") -> null
Index: 4  -> (8, "B") -> null

4.2. 開放尋址法(Open Addressing)

1.原理

開放尋址法在發(fā)生哈希沖突時,會在哈希表的數組中尋找下一個可用的桶來存儲沖突的元素。

常用的方法包括線性探測、二次探測和雙重哈希等。

2.特點

  • 使用數組存儲數據:所有數據都存儲在哈希表的原始數組中,不需要額外的鏈表或其他數據結構。
  • 查找時間:在平均情況下,查找時間復雜度與負載因子密切相關,負載因子過高可能導致性能下降。

3.示例

仍然使用相同的哈希函數 h(key) = key mod 5,并且存在以下鍵值對:

  • (3, "A")
  • (8, "B")
  • (9, "D")

假設當前哈希表的索引結構如下:

Index: 0  -> null
Index: 1  -> null
Index: 2  -> null
Index: 3  -> (3, "A") 
Index: 4  -> (8, "B") 

當插入鍵 9 時,計算得到 h(9) = 4,但索引 4 已經被占用,因此會采取開放尋址法策略查找下一個可用位置。這個位置是索引 0(線性探測),最終得到如下數據結構:

Index: 0  -> (9, "D")
Index: 1  -> null
Index: 2  -> null
Index: 3  -> (3, "A") 
Index: 4  -> (8, "B") 

常用的探測方法

1、線性探測(Linear Probing)

  • 當發(fā)生沖突時,逐個檢查下一個可用的桶。通過簡單地向后移動(對當前索引加 1)來查找下一個位置。
  • 例如,如果索引 ii 已經被占用,就檢查 (i+1)(i+1), (i+2)(i+2),...直到找到空桶。

這種方法的實現如下:

public int linearProbe(int hash, int i) {
    return (hash + i) % table.length;
}

2、二次探測(Quadratic Probing)

    • 對于每次沖突,使用二次函數(例如,i2i2)的方式查找下一個位置。這有助于減少碰撞和聚集問題。
    • 例如,如果索引 ii 已經被占用,就檢查 (i+12)(i+12),(i+22)(i+22),(i+32)(i+32),...直到找到空桶。

    實現類似于:

    public int quadraticProbe(int hash, int i) {
        return (hash + i * i) % table.length;
    }

    3、雙重哈希(Double Hashing)

    • 兩個不同的哈希函數同時使用,第一次利用主哈希函數獲取初步的索引,若發(fā)生沖突,則根據第二個哈希函數計算步長。這種方法能夠減小聚集問題。
    • 例如,如果主哈希函數返回的索引 h1h1,而第二個哈希函數返回 h2h2,那么如果發(fā)生沖突,查找下一個位置的方法為:
    public int doubleHash(int hash, int i) {
        return (hash + i * secondHash(key)) % table.length;
    }

    心得

    在開放尋址法中,探測的基礎是通過某種方式計算下一個桶的索引,從而避免沖突并正確處理數據。

    每種探測方法(線性、二次、雙重)各有優(yōu)缺點,實際使用時可以根據應用需求、性能和負載因子來選擇合適的探測方式。

    總結

    以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

    相關文章

    • springboot啟動mongoDB報錯之禁用mongoDB自動配置問題

      springboot啟動mongoDB報錯之禁用mongoDB自動配置問題

      這篇文章主要介紹了springboot啟動mongoDB報錯之禁用mongoDB自動配置問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
      2024-05-05
    • java實現微信公眾號發(fā)送模版消息

      java實現微信公眾號發(fā)送模版消息

      這篇文章以訂單推送為例,主要為大家詳細介紹了java實現微信公眾號發(fā)送模版消息,具有一定的參考價值,感興趣的小伙伴們可以參考一下
      2018-04-04
    • SpringCloud讓微服務實現指定程序調用

      SpringCloud讓微服務實現指定程序調用

      這篇文章主要介紹了SpringCloud讓微服務實現指定程序調用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
      2020-06-06
    • maven多模塊pom配置實例詳解

      maven多模塊pom配置實例詳解

      這篇文章主要介紹了maven多模塊pom配置實例代碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
      2024-01-01
    • Java設計模式之策略模式深入刨析

      Java設計模式之策略模式深入刨析

      策略模式屬于Java 23種設計模式中行為模式之一,該模式定義了一系列算法,并將每個算法封裝起來,使它們可以相互替換,且算法的變化不會影響使用算法的客戶。本文將通過示例詳細講解這一模式,需要的可以參考一下
      2022-05-05
    • SpringBoot ResponseBody返回值處理的實現

      SpringBoot ResponseBody返回值處理的實現

      這篇文章主要介紹了SpringBoot ResponseBody返回值處理的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
      2020-11-11
    • SpringMVC實現Controller的三種方式總結

      SpringMVC實現Controller的三種方式總結

      這篇文章主要介紹了SpringMVC實現Controller的三種方式總結,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
      2022-02-02
    • SpringCloud中的OpenFeign調用解讀

      SpringCloud中的OpenFeign調用解讀

      OpenFeign是一個顯示聲明式的WebService客戶端,使用OpenFeign能讓編寫Web Service客戶端更加簡單OpenFeign的設計宗旨式簡化Java Http客戶端的開發(fā),本文給大家介紹SpringCloud之OpenFeign調用解讀,感興趣的朋友一起看看吧
      2023-11-11
    • Mybatis復雜查詢的實現

      Mybatis復雜查詢的實現

      本文主要介紹了Mybatis復雜查詢的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
      2024-09-09
    • mybatis的if判斷不要使用boolean值的說明

      mybatis的if判斷不要使用boolean值的說明

      這篇文章主要介紹了mybatis的if判斷不要使用boolean值的說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
      2020-11-11

    最新評論