当HashMap在初始化没有指定容量的情况下,首次添加元素时,数组的容量为16;当超出阈值,数组容量为扩容为之前的2倍。 为什么HashMap每次扩容都是之前的2倍?而不是像ArrayList首次为10,后续
当HashMap在初始化没有指定容量的情况下,首次添加元素时,数组的容量为16;当超出阈值,数组容量为扩容为之前的2倍。 为什么HashMap每次扩容都是之前的2倍?而不是像ArrayList首次为10,后续为1.5倍呢?2倍不是很浪费空间吗? HashMap的putVal方法源码,如下图所示: 其中 n 为数组的长度,n - 1 为数组的最大索引值。(n - 1) & hash 的意思是将每个元素的key的hash值,与最大索引值-1进行相与操作,得出该元素在数组中的位置。hash是添加的元素进过哈希函数计算出来的值。 每次扩容后的数组长度如下表: 与运算的规则如下,只要有一个0,结果就是0;两个同时为1,结果才是1。
假如HashMap的容量不是2的n次幂,设容量为10,二进制为01010,(n-1)的二进制是01001,向里面添加同样的元素9,12,13,15,结果为: 可以看出,9,13,15得出的结果都是9,index相同,hash碰撞严重。 当HashMap的容量是16时,它的二进制是10000,(n-1)是15,二进制表示是01111,和hash值9,12,13,15进行与运算,计算结果如下: 还是9,12,13,15。可以看出,与运算后得出不同的值,使得添加的元素能够均匀分布在集合中不同的位置上,避免hash碰撞。 综上所述,HashMap计算添加元素的位置时,使用的位运算,这是高效的运算; 另外,HashMap的初始容量是2的n次幂,扩容也是2倍的形式进行扩容,是因为容量是2的n次幂,可以使得添加的元素均匀分布在HashMap中的数组上,减少hash碰撞,避免形成链表的结构,使得查询速度降低! |
2021-06-05
2021-05-27
2021-05-26
2021-06-05
2021-05-16