HashMap的初始化大小為什么是2的冪

HashMap的初始化大小為什么是2的冪

首先看下java初始化大小的源碼(代碼來自jdk1.8)

   //構造方法
   public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
       // 這里是初始化的長度
        this.threshold = tableSizeFor(initialCapacity);
    }
    
    //初始化長度的方法 
    static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

我們可以看到在初始化長度的不管我們傳入的是多少秧秉,其實真實的長度并不一定使我們傳入的值。它底層進行了一些運算。這個運算的結果是比我們傳入的參數(shù)要大削茁,而且是離我們傳入的參數(shù)最近的2的冪的數(shù)瓢宦。

運算原理案例:(假如我們傳入cap=5)

核心原理:從左到右斥季,使用左邊第一個`1`填充后面的所有位置
    
int n = cap -1;   n=4   00000100
n|= n>>>1;     n做無符號右移1位再和n做 `|`運算锦溪,
               n>>>1:  00000100  -> 00000010
               |n   :  00000100   |
                       00000010   
                    ------------------
                  結果:00000110
                   
n|=n>>>2;    n做無符號右移2位再和n做 `|`運算,
               n>>>2:  00000110  -> 00000001 10(后面兩位超出邊界舍棄)
               |n   :  00000110   |
                       00000001   
                    ------------------
                  結果:00000111
                   
...
      以此類推就可以將任何傳入的參數(shù)改變?yōu)楸人蟮亩沂请x它最近的2的冪
                   

為什么初始化的大小必須是2的冪

原因有兩點:1.加快哈希運算 2.減少哈希沖突

1.加快哈希運算

我們都知道比如向hashMap中存入一個值,通常做法是對這個值求hashCode()得到一個數(shù)hash,然后在用hash對集合長度求余數(shù),也就是 hash%length=positon得到的結果就是存放的位置综苔。

但是求余%的運算效率比較低惩系。有沒有更快的運算呢?答案是使用&運算如筛。但是使用&運算怎么樣才能和使用%效果一樣呢堡牡?那就是,當HashMap的長度為2的冪的時候一下公式就成立了:hash%length==hash&(length-1)杨刨。

所以就可以使用&運算來求位置下標了晤柄。

2.減少哈希沖突,保證數(shù)據(jù)分散

使用2的冪為長度,則length-1后為奇數(shù)妖胀,該奇數(shù)轉為2進制后最后一位肯定是1芥颈。

假如長度為4,則長度-1為3,再轉為2進制==0000011,該值與任何hash&運算都會形成==奇數(shù)==或者==偶數(shù)==兩種情況,保證數(shù)據(jù)時分散的赚抡。

可能有人會想這有什么用爬坑?那么我們假如長度不是4而是3,則3-1為2,再轉為2進制==0000010怕品,該值與任何hash&運算都會形成==偶數(shù)==,那也就是說我的奇數(shù)的下標都不能用了妇垢。這樣就不僅浪費一般的空間,而且增加了hash沖突的概率.

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肉康,一起剝皮案震驚了整個濱河市闯估,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吼和,老刑警劉巖涨薪,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異炫乓,居然都是意外死亡刚夺,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門末捣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侠姑,“玉大人,你說我怎么就攤上這事箩做∶Ш欤” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵邦邦,是天一觀的道長安吁。 經(jīng)常有香客問我,道長燃辖,這世上最難降的妖魔是什么鬼店? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮黔龟,結果婚禮上妇智,老公的妹妹穿的比我還像新娘。我一直安慰自己氏身,他們只是感情好巍棱,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著观谦,像睡著了一般拉盾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上豁状,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天捉偏,我揣著相機與錄音,去河邊找鬼泻红。 笑死夭禽,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的谊路。 我是一名探鬼主播讹躯,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了潮梯?” 一聲冷哼從身側響起骗灶,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎秉馏,沒想到半個月后耙旦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡萝究,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年免都,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帆竹。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡绕娘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出栽连,到底是詐尸還是另有隱情险领,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布升酣,位于F島的核電站舷暮,受9級特大地震影響,放射性物質發(fā)生泄漏噩茄。R本人自食惡果不足惜下面,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绩聘。 院中可真熱鬧沥割,春花似錦、人聲如沸凿菩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衅谷。三九已至椒拗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間获黔,已是汗流浹背蚀苛。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留玷氏,地道東北人堵未。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像盏触,于是被迫代替她去往敵國和親渗蟹。 傳聞我的和親對象是個殘疾皇子块饺,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355