为什么HashMap的数组长度是2的幂

简介: 为什么HashMap的数组长度是2的幂

为什么HashMap的长度一定是2的次幂呢?


今天和朋友聊天被问到HashMap的数组长度为什么是2的倍数。说实话挺惭愧的,秋招结束了,还不能完整的给出一个完整的答案。


今天和朋友聊天被问到HashMap的数组长度为什么是2的倍数。说实话挺惭愧的,秋招结束了,还不能完整的给出一个完整的答案。


我知道了HashMap的数据结构,也知道了什么是Hash冲突,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。


对于第一个问题针对的是hashmap数组扩容时,新数组length = 原数组length * 2,沿用前面的例子(array.length = 2^4 = 16,二进制10000),array.length 乘以 2 ,即二进制左移一位,由 10000 变成 100000。此时需要重新计算数组槽中的元素位置,如果槽中是链表,链表中每个元素都需要重新计算位置(这里不考虑红黑树)。t同时,由于get时需要对链表其进行遍历,链表越长检索效率越差。那么,计算出的key值落点越平均,hash冲突的可能性越小。key值的落脚点为key的hash值与数组长度作取余操作,记作key.hashcode % array.length。


数学角度考虑,保持array.length为质数会使得计算结果更均衡,hashTable就是这么做的(数组初始值11)。但 hashmap 中 array.length 偏偏选择了2的次幂,是个合数.完全出于性能考虑!


结论:当 array.length长度是2的次幂时,key.hashcode % array.length等于key.hashcode & (array.length - 1)。


以长度为16 , key值为 10011011001 举例,也就是


array.length = 16 , 二进制为:10000


array.length - 1 = 15 , 二进制为 : 1111


key.hashcode % array.length : 1001


key.hashcode & array.length-1 : 1001


计算过程:


100 1101 1001


& 1111


1001


发现两者计算的结果是一样的。


最终计算的结论就是:


10011011001 & ( 10000 - 1 ) = 10011011001 & 1111 = 1001 = 10011011001 % 10000

2554cf1fe44248b4ace60adc475ddff8.png


总结:


对hashmap而言,数组长度为2次幂有两点好处:

& 代替 %,可以提升性能

数组扩容时,仅仅关注 “特殊位” 就可以重新定位元素

仅关注 “特殊位” 就可以重新定位元素

性能,性能,还是性能……

相关文章
|
1月前
|
索引
HashMap中hash()方法的位运算
HashMap中hash()方法的位运算
HashMap中hash()方法的位运算
|
1月前
获取数组长度
获取数组长度
21 1
|
1月前
|
算法 前端开发
二的幂数组中查询范围内的乘积
二的幂数组中查询范围内的乘积
21 0
判断是否为2的次幂
判断是否为2的次幂
76 0
015.利用数组求前n个质数
015.利用数组求前n个质数
39 0
|
存储 Java
为什么不建议使用实数作为 HashMap 的 key?
为什么不建议使用实数作为 HashMap 的 key?
162 0
|
机器学习/深度学习
运用 lowbit 判断 2 的幂
运用 lowbit 判断 2 的幂
|
算法 Java
只出现一次的数(哈希/排序/位运算)
只出现一次的数(哈希/排序/位运算)
给定一个由正数,负数和0组成的整数数组,将所有为0的元素,挪到数组末尾。要求时间复杂度O(n)
给定一个由正数,负数和0组成的整数数组,将所有为0的元素,挪到数组末尾。要求时间复杂度O(n)
223 0
给定一个由正数,负数和0组成的整数数组,将所有为0的元素,挪到数组末尾。要求时间复杂度O(n)
|
存储 算法 索引
HashMap 容量为什么总是为 2 的次幂?
HashMap是根据key的hash值决策key放入到哪个桶(bucket)中,通过 tab=[(n - 1) & hash] 公式计算得出,其中tab是一个哈希表。
HashMap 容量为什么总是为 2 的次幂?