美文网首页
ConcurrentHashMap为什么每次扩容时候扩大一倍

ConcurrentHashMap为什么每次扩容时候扩大一倍

作者: 式微胡不归_e8b4 | 来源:发表于2018-12-28 17:39 被阅读0次

问题:为什么ConcurrentHashMap每次扩容的时候扩大一倍?

答案:通过位运算,代替模运算,速度更快



众所周知:key要通过哈希函数变成一个数字,然后存放在哈希表对应的位置中。存放会涉及到一些哈希冲突的时候,就通过链表,或者平衡二叉树,将新key放在旧key后面。

例子:"name"(key)    "zhangsan"(value) ,当前的哈希表容量是8

1.    通过java的hashCode() 函数可以计算出哈希码

2.    “name”字符串的哈希码是3373707(十进制),1100110111101010001011(二进制)

3.    将1100110111101010001011与哈希表的容量8-1 = 7做一次与运算(&)

前面的位数忽略只保留最后三位

        结果显示是011也就是十进制的3

4.    将key放入大小为8的哈希表中

此处省略value

5.    其他的key:

        “age”         96511    10111100011111111   最后三位是111 与 7(111)做与运算得到111,放入第七个空格中

        “email”  96619420    101110000100100101110011100,做与运算,放入100位置,也就是4号空格中

        "phone"    194811     101111100011110011,与7做与运算,放入3号空格,哈希冲突,以链表形式放到name后面

这个时候哈希表已经变成这样子啦

6.    当我们要扩展哈希表为16个空格的时候,16-1=15 ,15的二进制是1111

        这个时候我们再比较一下

        “name”的哈希码1100110111101010001011

        “phone”的哈希码101111100011110011

        当他们与15(1111)做与运算的时候,和与 7(111)做与运算的时候有什么不同?

        “name”:

name

       “phone”

phone

    这时候,name的结果是(11)1011,“phone”结果是(3)0011

    发现:name因为高一位是1,所以应该离开到11号空格,phone因为高一位是0,还会留在3号空格中!!

    这就是扩大一倍带来计算上的简便!!

            当初容量是8,8-1=7,7的二进制是111

            现在容量是16,16-1=15,15的二进制是1111

            因为他们都是全为1的形态,而扩大一倍后只是高位加了一个1,所以会留有大概一半的key在原来的空格,而有一半的key到相同的别的空格中,比如都是从3号位置到了11号位置中,这样也便于复制。

            通过位运算,代替了模运算!

相关文章

网友评论

      本文标题:ConcurrentHashMap为什么每次扩容时候扩大一倍

      本文链接:https://www.haomeiwen.com/subject/hahelqtx.html