hashmap是廣大程式設計師在做專案的時候,最喜歡使用的乙個工具,用的最多但了解的並不與使用頻率成正比,很多人都是只停留在會put/get而已。這樣在面試的時候其實很不吃香的,知道面試會問hashmap就去網上看面經,但麵經上的關於hashmap的東西嘛。。。千篇一律,看完之後食之無味棄之可惜。所以去看原始碼是乙個了解hashmap很好的方式也是很重要的途徑。這篇文章不會涉及太多hashmap原始碼的東西,我主要拿來其中的一點與大家進行分享——雜湊方法static final int hash(object key);
static
final
int hash(object key)
看上去,沒啥太複雜的東西,就是拿來k的hashcode,高低16位做亦或,在後續進行模擬取模操作。
那麼問題來了,你真的知道他為什麼要高低16位亦或嗎?或許你會跟我說,人家網上不是都說了,為了讓hash做的更均勻,盡量避免衝突嗎?那我們就來做乙個實驗,看一看這個東西到底是不是像網上說的那樣:
實驗步驟很簡單,我們隨便敲一些字串:
list(
"asf","132sg","23ga","13erasd","alireio",
"2oosoi","qooizoi","!#@$sdgta","asd123zadsf#@","qasdolkado!#@",
"} ,另一方面取出m個a,後n位衝突的概率是 1-2^n!/((2^n-m)! * 2^)
就是說網上說的什麼hash函式為了解決hashcode後n位相等的情況,到**查都是這個答案,那麼我想問你們想過沒有,乙個整數字操作後得到的,難道不也是乙個整數嗎?難道他就不會出現相等的情況嗎?所以對這類人我不做過多評價。
所以這麼看來hash函式其實根本沒有降低衝突率,衝突率降低的唯一方法是降低 m/n 的值,熟悉嗎?這不就是hashmap的額定大小和負載因子幹的活嗎?
那麼問題來了,那這個hash存在的意義又是什麼呢???我思考了許久,發現了乙個事情,就是說上面的推論的大前提是:任意整數!也就是說前提是說key的hashcode足夠均勻!那麼這個時候,我們是否應該把關注點放在hashcode身上了?如果hashcode足夠均勻,那麼hash函式自然就起不到作用,那如果他不是足夠均勻的呢?
根據這個入手點,我最後得出乙個結論,
這個高低十六位亦或的操作,是基於假設key類的設計者在設計hashcode的時候可能設計出bad hashcode,在設計這個bad hashcode的時候bad的點可能在於hashcode的後n位不均勻,而不是bad在hashcode的高低16位亦或後的後n位不均勻!這就是跳了一層的感覺。
可能比較繞口,我們來舉個栗子說明一下。
對於乙個類,我們如果想重寫hashcode,一般會根據某個字段某個屬性,按照一定的公式,去計算吧?那麼這個計算的出的結果,很可能遵循著某個線性的規律,這個規律導致了物件的hashcode的後n為可能比較集中。
那麼,對於高低16位亦或來說就不一樣了,我總不能特意去設計乙個hashcode經過高低16位亦或的結果比較集中的hash吧?比如?像下面這種?
int hashcode()
那我估計這樣的類作為key的話,hashmap的設計者可能會跑出來殺了你的 HashMap的一道簡單例子
public class hashmapexample system.out.println the values are 因為map的值有可能重複,所以不能用set,要用collection collection valuecol m1.values iterator ival valuecol....
P說 多執行緒HashMap產生死迴圈
在1.7及以前,使用hashmap進行put操作時,當元素超過閾值時,會觸發resize操作,這時候可能就會出現死迴圈的情況,導致cpu佔用率達到100 首先,我們要先了解hashmap的資料結構,hashmap的主幹是乙個entry陣列。entry是hashmap的基本組成單元,每乙個entry包...
從一道演算法題說去1
宣告 演算法學習來自,7月演算法,面試 演算法 機器學習 找工作就上七月演算法 1.今天學習的演算法是 lcs,最長公共子串行,屬於典型的動態規劃基礎題。2.實踐 algorithm lcs include include include include include using namespac...