哈希表:根據關鍵碼值(key value)直接進行訪問的數據結構,也就是說,它經過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找速度,這個映射函數叫作哈希函數,存放記錄的數組叫作哈希表。算法
給定表M,存在函數f(key),對任意給定的關鍵字值key,代入函數後若能獲得包含該關鍵字的記錄在表中的地址,則稱表M爲哈希(Hash)表,函數f(key)爲哈希(Hash) 函數。數組
舉例:新華字典,我想要獲取「按」字詳細信息,去根據拼音an去查找拼音索引,首先去查an在字典的位置,獲得「安」,這個過程就是鍵碼映射。在公式裏,就是經過key去查找f(key)。其中,按就是關鍵字(key),f(key)就是字典索引,也就是哈希函數,查到的頁碼4就是哈希值。緩存
根據設定的哈希函數f=H(key)和處理衝突的方法,將一組關鍵字映像到一個有限的連續的地址集上,並以關鍵字在地址集中的」象」做爲記錄在表中的存儲位置,這一映像過程,稱爲構造哈希表(散列表)。服務器
構造哈希函數的方法不少,實際工做中要根據不一樣的狀況選擇合適的方法,總的原則是儘量少的產生衝突。網絡
一般考慮的因素有關鍵字的長度和分佈狀況、哈希值的範圍等。數據結構
如:當關鍵字是整數類型時就能夠用除留餘數法;若是關鍵字是小數類型,選擇隨機數法會比較好。分佈式
若key1≠key2, 而f(key1)=f(key2), 則這種現象稱爲衝突,且key1和key2對哈希函數f來講是同義詞。
函數
用開放定址法解決衝突的作法是:性能
用開放定址法解決衝突的作法是:當衝突發生時,使用某種探測技術在散列表中造成一個探測序列。沿此序列逐個單元地查找,直到找到給定的關鍵字,或者碰到一個開放的地址(即該地址單元爲空)爲止(若要插入,在探查到開放的地址,則可將待插入的新結點存人該地址單元)。查找時探測到開放的地址則代表表中無待查的關鍵字,即查找失敗。
簡單的說:當衝突發生時,使用某種探查(亦稱探測)技術在散列表中尋找下一個空的散列地址,只要散列表足夠大,空的散列地址總能找到。spa
按照造成探查序列的方法不一樣,可將開放定址法區分爲線性探查法、二次探查法、雙重散列法等。
hi=(h(key)+i) % m ,0 ≤ i ≤ m-1
基本思想是:
探查時從地址 d 開始,首先探查 T[d],而後依次探查 T[d+1],…,直到 T[m-1],此後又循環到 T[0],T[1],…,直到探查到 有空餘地址 或者到 T[d-1]爲止。
hi=(h(key)+i*i) % m,0 ≤ i ≤ m-1
基本思想是:
探查時從地址 d 開始,首先探查 T[d],而後依次探查 T[d+1^2],T[d+2^2],T[d+3^2],…,等,直到探查到 有空餘地址 或者到 T[d-1]爲止。
缺點是沒法探查到整個散列空間。
hi=(h(key)+i*h1(key)) % m,0 ≤ i ≤ m-1
基本思想是:
探查時從地址 d 開始,首先探查 T[d],而後依次探查 T[d+h1(d)], T[d + 2*h1(d)],…,等。
該方法使用了兩個散列函數 h(key) 和 h1(key),故也稱爲雙散列函數探查法。
定義 h1(key) 的方法較多,但不管採用什麼方法定義,都必須使 h1(key) 的值和 m 互素,才能使發生衝突的同義詞地址均勻地分佈在整個表中,不然可能形成同義詞地址的循環計算。
該方法是開放定址法中最好的方法之一。
拉鍊法解決衝突的作法是:
將全部關鍵字爲同義詞的結點連接在同一個單鏈表中。
若選定的散列表長度爲 m,則可將散列表定義爲一個由 m 個頭指針組成的指針數組 T[0..m-1] 。
凡是散列地址爲 i 的結點,均插入到以 T[i] 爲頭指針的單鏈表中。
T 中各份量的初值均應爲空指針。
在拉鍊法中,裝填因子 α 能夠大於 1,但通常均取 α ≤ 1。
這種方法是同時構造多個不一樣的哈希函數:
Hi=RH1(key) i=1,2,…,k
當哈希地址Hi=RH1(key)發生衝突時,再計算Hi=RH2(key)……,直到衝突再也不產生。這種方法不易產生彙集,但增長了計算時間。
將哈希表分爲基本表和溢出表兩部分,凡是和基本表發生衝突的元素,一概填入溢出表。
哈希表(hash table)是哈希函數最主要的應用。
哈希表是實現關聯數組(associative array)的一種數據結構,普遍應用於實現數據的快速查找。
用哈希函數計算關鍵字的哈希值(hash value),經過哈希值這個索引就能夠找到關鍵字的存儲位置,即桶(bucket)。哈希表不一樣於二叉樹、棧、序列的數據結構通常狀況下,在哈希表上的插入、查找、刪除等操做的時間複雜度是 O(1)。
查找過程當中,關鍵字的比較次數,取決於產生衝突的多少,產生的衝突少,查找效率就高,產生的衝突多,查找效率就低。所以,影響產生衝突多少的因素,也就是影響查找效率的因素。
影響產生衝突多少有如下三個因素:
哈希函數是否均勻;
處理衝突的方法;
哈希表的加載因子。
哈希表的加載因子和容量決定了在何時桶數(存儲位置)不夠,須要從新哈希。
加載因子太大的話桶太多,遍歷時效率變低;太大的話頻繁 rehash,致使性能下降。因此加載因子的大小須要結合時間和空間效率考慮。
在 HashMap 中的加載因子爲 0.75,即四分之三。
網絡環境下的分佈式緩存系統通常基於一致性哈希(Consistent hashing)。簡單的說,一致性哈希將哈希值取值空間組織成一個虛擬的環,各個服務器與數據關鍵字K使用相同的哈希函數映射到這個環上,數據會存儲在它順時針「遊走」遇到的第一個服務器。可使每一個服務器節點的負載相對均衡,很大程度上避免資源的浪費。
在動態分佈式緩存系統中,哈希算法的設計是關鍵點。使用分佈更合理的算法可使得多個服務節點間的負載相對均衡,能夠很大程度上避免資源的浪費以及部分服務器過載。 使用帶虛擬節點的一致性哈希算法,能夠有效地下降服務硬件環境變化帶來的數據遷移代價和風險,從而使分佈式緩存系統更加高效穩定。