栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么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次幂有两点好处:

& 代替 %,可以提升性能

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

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

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/603561.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号