hashmap申请内存为什么是2的幂?

620 阅读2分钟

    大家在查看hashmap的底层原理时都会看到“hashmap再申请生成新的数组结构时其数组元素个数是2的幂”。

    这是为什么呢? 不是2的幂就不可以吗? 大家可能相等这可能和内存的分配有关系,可以提升内存分配速度,或者方便元素的查找等。

    在具体解释前先说下hashmap的元素的查找:

   代码在获取hashmap数据结构中的每个key的值时:

  •  先将key进行hash函数的计算,获取到一个大的整数
  •  使用大的整数 h%L (L是数组长度)
  •  找到对应的数组下标,比较存储的key和查找key是否一致,不一致时,如果后面还有链表就进行遍历。

   从上面可以看到每次进行查找时都需要进行取模运行,而cpu对于取模运算时比较慢的,而对于逻辑与 或 非运算很快,比较是二进制位处理。如果数组元素个数是2的幂时就可以将取模运算转化为与运算,大大提高计算速度:

                            

                                           h%L = h&(L-1)


现在咱们证明下上面得结论:

  •    h(key进行hash后的大整数)
  •    length(数组长度,2的幂)length=2^x


   假设h小于length: 

     h小于length时 h%length=h 

    length-1=2^0+2^1+.....2^(x-1)(根据2进制的规则可以转为这种形式) 可以看到所有位都是1,h<=length-1,这样不管如何只要h对应二进制位位1时,length-1对应的二进制位都是1. 

    可以得出结论: h&(length-1)=h=h%length; 


 假设h大于length:

  •  h=n+m*length
  •  h%length=n (n<length)
  •  length=2^x;
  •   length-1=2^0+2^1+.....2^(x-1) 
  •  h&(length-1)=(n+m*length)&(2^0+2^1+.....2^(x-1)) 

      其中m*length转化为二进制时,其与length-1的与操作结果都是0(因为length=2^x, 变大m倍时,其变为二进制是等于2^Y1+2^Y2+2^Y3...,其中Y>=x)

    所以 (n+m*length)&(2^0+2^1+.....2^(x-1)) = n;

     得出结论 h%length = h&(length-1)