一文看懂HashMap扩容为何是2的n次幂

1.什么是HashMap?

    

    HashMap是Java中的集合类,是存放键值对形式的数据(Key和Value),例如QQ帐号和QQ密码,QQ帐号就是Key而密码则是Value。以下图所示(假如QQ帐号为123456,密码为abcdef)数组



    

    运行结果以下所示微信





    若是存放相同的Key,那么Value将会被覆盖,相似于QQ更改密码,帐号不会变,只有密码会进行更改。less





    运行结果以下所示编辑器

    




2.为何扩容2的n次幂?



    首先先看一下HashMap中的putVal方法(存值的)和resize方法(扩容的),之因此HashMap扩容是2的n次幂和这两个方法有千丝万缕的联系。函数



    经过putVal方法能够看出来HashMap在存值时会先把key的hash值和扩容后的长度进行一次按位与运算,其中hash是在hash方法中把key进行计算后的出来的结果,n是扩容的长度(也就是数组的长度,默认为16),而后判断是否hash碰撞在进行不一样的存储。以下图源码所示。spa





    经过resize方法能够看出来扩容时会新建一个tab,而后遍历旧的tab,将旧的元素进行e.hash & (newCap - 1)的计算添加进新的tab中,也就是(n - 1) & hash的计算方法,其中n是集合的容量,hash是添加的元素通过hash函数计算出来的hash值。以下图源码所示。.net





    之因此这样2n扩容和上面的两个方法有极大的关系,首先他们都使用了按位与运算按位与运算就是把值先变成二进制而后进行运算,若是有0则为0,都为1时则输出为1,HashMap默认容量为16那么在存放到数组时就是n-1也就是15,而15二进制则是1111扩容后为32-1及111111113d

,若是都为1的状况下是能够极大的减小hash碰撞,增长效率的。blog



    经过下面例子来看一下当容量为11111111时按位与运算的结果,经过下面的结果能够看出来结果很分散,大大减小了hash碰撞的发生。
ip


    再看一下当容量不为11111111而是为其余值的时候,经过下面的结果能够看出,一、二、4跟不一样的值进行hash运算可是结果倒是相同的,也就是发生了hash碰撞。


    经过上面的对比能够看出来11111111和其余值

比较大大的减小了hash碰撞的发生,这样就是为什

么HashMap为何扩容采用2的n次幂的缘由。




本文分享自微信公众号 - 大猫的Java笔记(damaoJava)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索