文章目录
- put() 方法的流程
- 扩容流程
- 为什么它会按照2的幂次方进行扩容呢?
put() 方法的流程
下面我们通过分析源码来总结一下 put() 方法的流程
扩容流程
根据上图的分析,就可以总结出 HashMap 的扩容流程:
在插入元素时,会先调用hash方法,得到一个hash值,在插入前先判断一下这个数组的长度是否为空或者是否位0,如果为空或者为0的话,就进行初始化,将数组的长度初始化为16,初始化完之后,就会根据hash值计算出该元素在数组中的存储位置,如果该位置为空的化,就直接创建一个节点,插入进入。如果说该位置不为空的话,就会判断一下链表还是红黑树,如果是链表的话,就进行尾插,插入完成之后,就会再判断如果链表中节点的个数大于8并且数组的长度大于64,链表就会转化成红黑树,上述的插入操作进行完之后,size++,就会判断键值对的数量是否大于 初始化容量*负载因子的乘积,如果大于,此时就会对数组进行扩容,而它的扩容是按照2的幂次方进行扩容的。
为什么它会按照2的幂次方进行扩容呢?
- 索引的计算效率要高
如果,当hashmap的容量是2的幂次方时,hash &(length-1) 和 hash % length 所得到的值是一样的。因为,& 运算只涉及到按位与操作,而 % 运算需要执行完整的除法和取余运操作,所以,& 更快,按照这种方式也就提升了索引计算的效率。
- 减少冲突
2 的幂次方的容量可以使得存储位置分布更加均匀,因为,在哈希函数中,它是将hashcode的低16异或上了高16位,这种方式就使得哈希码的高位信息也能参与到数组索引计算中,从而提高哈希码的均匀性,而在计算存储位置时,是按照 hash & (length-1),length-1的,length是2次幂,这样所得到的数值的二进制就是全1,比如,初始化容量是16,减1后15,15的二进制就是1111, 此时就可以让哈希码的低位能够完全参与到位运算中,从而实现高效的分布。
- 扩容时元素重新分配简单
。
- 扩容时元素重新分配简单
由于新的容量是2 的次幂,所以,在进行完扩容之后,只需要将原数组中的元素重新分配到新数组的相应位置即可,这就大大简化了扩容操作的复杂度