沒有源碼的解析都是瞎扯淡系列之HashMap#tableSizeFor()方法

```java
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;
}
```

原文查看[豬哥亮博客](http://zglbk.cn/blog/78)

發現什麼規律沒?
1.無符號右移最終的目的就是將n的二進制32位都變成0既:

原文查看[豬哥亮博客](http://zglbk.cn/blog/78)

不信我們可以吧java int類型的最大值 0x7fffffff按照上面的無符號右移

原文查看[豬哥亮博客](http://zglbk.cn/blog/78)

發現沒,移到16的時候就都變成了0,這裏也可以說明爲什麼是16而不是8或者32,這個是因爲java的int類型用4個字節32位來進行存儲的。再往後也就沒什麼意義。而如果是小於16那麼會出現移動不完的情況
2.異或的最終目的是將二進制的最高位的第一個1往後的0都變成1
同樣拿int的最大值 0x7fffffff 做個實驗

原文查看[豬哥亮博客](http://zglbk.cn/blog/78)

看見沒亦或出來的一直都是它本身,說了這麼多這一頓左移+亦或之後會得到什麼結果呢?
來看看

```
傳入1 = 1
傳入2 = 2
傳入3 = 4
傳入4 = 4
傳入5 = 8
...
傳入8 = 8
傳入9 = 16
...
傳入16 = 16
傳入17 = 32
...
傳入32 = 32
```

也就是說上面這一端操作之後不管你傳進來的是什麼那麼它都會**算出比你傳進來的值大的第一個二的次方減1**
0、1、3、7、15、31、63、127、255...(注:這裏說的是上面的運算,還沒牽扯到第一行的+1和後面的(n+1))
而後又做了

```java
(n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
```

也就是當n小於0是返回1 當n大於等於int的最大值時 0x7fffffff 返回int的最大值否者返回n+1也就是2的n次方
1、2、4、8、16、32、64、128、256...也就是說不管你傳進來的初始值是多少最終都會被HashMap計算出來的值取代(2的n次方)。
回過頭分析這裏爲什麼第一行會有 int n = cap - 1; 通過上面一系列說明我們可以發現計算的結果是**算出比你傳進來的值大的第一個二的次方減**(注:上面的二的次方減-1和這裏的不-1要區分,這裏是最終的計算結果),那如果你傳進來的數字正好是2的n次方比如 **8** 那麼如果不減1那麼最終算出的結果是

原文查看[豬哥亮博客](http://zglbk.cn/blog/78)

最終的結果是15再+1也就是16,也就是說你本來想創建一個容量爲8的HashMap結果給你創建了一個16的容量,那麼剩下的是不是就浪費了呢,所以需要先減去1再就是8-1=7,最終算出n=7再加1也就是8就正好對了,如果是9呢?9-1=8最後算出n=15+1 = 16 也就是會給你創建16個容量的容器
好了這個方法就說到這裏,神奇嗎? 算上{}這個方法也就9行的代碼卻需要這麼一大堆的文字來分析與描述而且我這裏還不一定講的清楚。那這裏爲什麼會使用2的指數冪作爲容器的初始值我們下一次在容器擴容好數據拷貝的時候再來分析,以爲在那裏它將這寫算法的運用說的凌厲盡致。也只有在使用的時候纔會將其說清楚。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章