为什么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

在这里插入图片描述

总结:

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

& 代替 %,可以提升性能

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值