HashMap中為什么數(shù)組的長度為2的冪次方

Java中HashCode算法詳解

Java中的集合,比如HashMap/HashSet/HashTable在實現(xiàn)上都用到了hashCode算法,用來計算元素在數(shù)組中的位置毡代。hashCode是Object類中的一個方法,所以,所有的Java類都有這個方法苗沧,只是一些類對這個方法進行了覆寫,下面以String類的實現(xiàn)為例進行說明:

public int hashCode() {

????int h =hash;

? ? if (h ==0 &&value.length >0) {

????????char val[] =value;

? ? ? ? for (int i =0; i <?value.length; i++) {

????????h =31 * h + val[i];

? ? ? ? }

????????hash = h;

? ? }

????return h;

}

其實這個算法的實現(xiàn)很簡單炭晒,以“hangzhou”這個字符串為例待逞,計算過程如下:

第一步:int ‘h’

第二步:31 * (第一步結(jié)果) + int ‘a(chǎn)’

第三步:31 * (第二部結(jié)果) + int ‘n’

第四步:31 * (第三步結(jié)果) + int ‘g’

第五步:31 * (第四步結(jié)果) + int ‘z’

第六步:31 * (第五步結(jié)果) + int ‘h’

第七步:31 * (第六步結(jié)果) + int ‘o’

第八步: 31 * (第七步結(jié)果) + int ‘u’

可以得到“hangzhou”的hashcode為4740586。

為什么HashMap中的&位必須位奇數(shù)(length-1)

從key映射到HashMap數(shù)組的對應(yīng)位置需要一個Hash函數(shù):

index = Hash("hangzhou")

如何實現(xiàn)一個盡量分布均勻的hash函數(shù)呢网严?我們使用key的hashcode做某種運算:

index = hashCode("hangzhou") & (Length - 1) 其中识樱,Length為HashMap的長度,下面來演示整個過程:

1震束、“hangzhou”的hashcode為4740586怜庸,二進制表示為100 1000 0101 0101 1110 1010

2、假定HashMap的長度為默認(rèn)的16垢村,則Length - 1為15割疾,也就是二進制的1111

3、把以上兩個結(jié)果做與運算肝断,得到的結(jié)果為1010杈曲,也就是index為10

可以說,Hash算法最終得到的index結(jié)果完全取決于hashCode的最后幾位胸懈。

假設(shè)担扑,HashMap的長度為10,則Length - 1為9趣钱,也就是二進制的1001涌献,通過Hash算法得到的最終index為8,當(dāng)只有一個元素的時候這沒問題首有。但是我們再來試一個hashCode:100 1000 0101 0101 1110 1110時燕垃,通過Hash算法得到的最終的index也是8枢劝,另外還有100 1000 0101 0101 1110 1000得到的index也是8。也就是說卜壕,即使我們把倒數(shù)第二您旁、三位的0、1變換轴捎,得到的index仍舊是8鹤盒,說明有些index結(jié)果出現(xiàn)的幾率變大!侦副!而有些index結(jié)果永遠不會出現(xiàn)侦锯,比如二進制0000.

這樣,顯然不符合Hash算法均勻分布的要求秦驯。

反觀尺碰,長度16或其他2的冪次方,Length - 1的值的二進制所有的位均為1译隘,這種情況下亲桥,Index的結(jié)果等于hashCode的最后幾位。只要輸入的hashCode本身符合均勻分布固耘,Hash算法的結(jié)果就是均勻的两曼。

一句話,HashMap的長度為2的冪次方的原因是為了減少Hash碰撞玻驻,盡量使Hash算法的結(jié)果均勻分布。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末偿枕,一起剝皮案震驚了整個濱河市璧瞬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌渐夸,老刑警劉巖嗤锉,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異墓塌,居然都是意外死亡瘟忱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門苫幢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來访诱,“玉大人,你說我怎么就攤上這事韩肝〈ゲ耍” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵哀峻,是天一觀的道長涡相。 經(jīng)常有香客問我哲泊,道長,這世上最難降的妖魔是什么催蝗? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任切威,我火速辦了婚禮,結(jié)果婚禮上丙号,老公的妹妹穿的比我還像新娘先朦。我一直安慰自己,他們只是感情好槽袄,可當(dāng)我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布烙无。 她就那樣靜靜地躺著,像睡著了一般遍尺。 火紅的嫁衣襯著肌膚如雪截酷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天乾戏,我揣著相機與錄音迂苛,去河邊找鬼。 笑死鼓择,一個胖子當(dāng)著我的面吹牛三幻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播呐能,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼念搬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了摆出?” 一聲冷哼從身側(cè)響起朗徊,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎偎漫,沒想到半個月后爷恳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡象踊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年温亲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杯矩。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡栈虚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出史隆,到底是詐尸還是另有隱情节芥,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站头镊,受9級特大地震影響蚣驼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜相艇,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一颖杏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坛芽,春花似錦留储、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至活喊,卻和暖如春丐膝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背钾菊。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工帅矗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人煞烫。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓浑此,卻偏偏與公主長得像,于是被迫代替她去往敵國和親滞详。 傳聞我的和親對象是個殘疾皇子凛俱,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容