1. 程式人生 > >hash衝突的解決方法以及hashMap的底層實現

hash衝突的解決方法以及hashMap的底層實現

大家平時都用過hashMap,但是可能大家對hashMap的底層實現不太瞭解,同時對其中可能出現的hash衝突有些不瞭解,這幾天我翻了下資料,也稍微瞭解下,記錄下來,以免遺忘。

這裡寫圖片描述

上圖就是一個散列表(Hash table,也叫雜湊表),是根據關鍵碼值(Key value)而直接進行訪問的資料結構。也就是說,它通過把關鍵碼值對映到表中一個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做散列表。但是當關鍵字數量比較大的時候,難免就會造成一個問題,就是不一樣的關鍵字隱射到同一個地址上,這樣就造成了一個問題,就是hash衝突。那麼如何解決呢?

一般比較常用的方法有開放地址法:(內容來自百度百科)
1. 開放定址法:Hi=(H(key) + di) MOD m,i=1,2,…,k(k<=m-1),其中H(key)為雜湊函式,m為散列表長,di為增量序列,可有下列三種取法:
1.1. di=1,2,3,…,m-1,稱線性探測再雜湊;順序查看錶的下一單元,直至找到某個空單元,或查遍全表。
1.2. di=1^2,-1^2,2^2,-2^2,⑶^2,…,±(k)^2,(k<=m/2)稱二次探測再雜湊;在表的左右進行跳躍式探測。
1.3. di=偽隨機數序列,稱偽隨機探測再雜湊。根據產生的隨機數進行探測。

2 再雜湊法:建立多個hash函式,若是當發生hash衝突的時候,使用下一個hash函式,直到找到可以存放元素的位置。

3 拉鍊法(鏈地址法):就是在衝突的位置上簡歷一個連結串列,然後將衝突的元素插入到連結串列尾端,

4 建立公共溢位區:將雜湊表分為基本表和溢位表,將與基本表發生衝突的元素放入溢位表中。

底層的hashMap是由陣列和連結串列來實現的,就是上面說的拉鍊法。首先當插入的時候,會根據key的hash值然後計算出相應的陣列下標,計算方法是index = hashcode%table.length,(這個下標就是上面提到的bucket),當這個下標上面已經存在元素的時候那麼就會形成連結串列,將後插入的元素放到尾端,若是下標上面沒有存在元素的話,那麼將直接將元素放到這個位置上。
當進行查詢的時候,同樣會根據key的hash值先計算相應的下標,然後到相應的位置上進行查詢,若是這個下標上面有很多元素的話,那麼將在這個連結串列上一直查詢直到找到對應的元素。