JDK1.8的HashMap在很多方面都做了優(yōu)化改進,其中擴容時引入了高低位機制,table數(shù)組中某個位置的鏈表或者紅黑樹中的節(jié)點在擴容時,不需要重新按照以前的方式計算索引位置,而只要計算hash值在舊容量最高位對應的二進制是1還是0,是1則會移動到高位索引(原索引位置+原容量),是零則在低位索引也就是原位置。
舉例如下:
hash值h二進制為
0010 1100 1111 0001 1110 1110
舊容量為length=16,二進制為
0001 0000
length-1=0000 1111
那么擴容前索引位置為
h&(length-1)=1110=14
擴容后,容量為32,對應二進制為
0010 0000
新length-1=0001 1111
hash值對新容量計算索引時,可以看出最后四位二進制是不變的,與原容量時計算一致,唯一變化的是倒數(shù)第五位的二進制值,本例中hash對應新索引不變還是14,因為hash的倒數(shù)第五位為0
如果hash為0100 0001 0010,舊容量中索引為0010=2,新容量下索引為0001 0010=18=2+16。
結論
可見在擴容后,索引位置要嘛不變,要嘛移動舊容量個位置。
而判斷的依據(jù)就是hash值在擴容后容量-1的最高位對應的值,而擴容后容量-1的最高位其實就是擴容前容量的最高位。
因此可以通過h&oldcap來判斷,=0代表對應最高位為零,不移動位置;>0代表對應最高位不為零,需要移動到高位索引。