hashmap为什么容量是2的n次方
我们知道在hashmap中要找到某个元素,需要根据key的hash值来求得对应数组中的位置。如何计算这个位置就是hash算法。前面说过hashmap的数据结构是数组和链表的结合,所以我们当然希望这个hashmap里面的元素位置尽量的分布均匀些,尽量使得每个位置上的元素数量只有一个,那么当我们用hash算法求得这个位置的时候,马上就可以知道对应位置的元素就是我们要的,而不用再去遍历链表
所以我们首先想到的就是把hashcode对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。但是,“模”运算的消耗还是比较大的,能不能找一种更快速,消耗更小的方式那?java中时这样做的,
static int indexFor(int h, int length) { return h & (length-1); }
首先算得key得hashcode值,然后跟数组的长度-1做一次“与”运算(&)。看上去很简单,其实比较有玄机。比如数组的长度是2的4次方,那么hashcode就会和2的4次方-1做“与”运算。很多人都有这个疑问,为什么hashmap的数组初始化大小都是2的次方大小时,hashmap的效率最高,我以2的4次方举例,来解释一下为什么数组大小为2的幂时hashmap访问的性能最高。
看下图,左边两组是数组长度为16(2的4次方),右边两组是数组长度为15。两组的hashcode均为8和9,但是很明显,当它们和1110“与”的时候,产生了相同的结果,也就是说它们会定位到数组中的同一个位置上去,这就产生了碰撞,8和9会被放到同一个链表上,那么查询的时候就需要遍历这个链表,得到8或者9,这样就降低了查询的效率。同时,我们也可以发现,当数组长度为15的时候,hashcode的值会与14(1110)进行“与”,那么最后一位永远是0,而0001,0011,0101,1001,1011,0111,1101这几个位置永远都不能存放元素了,空间浪费相当大,更糟的是这种情况中,数组可以使用的位置比数组长度小了很多,这意味着进一步增加了碰撞的几率,减慢了查询的效率!
所以说,当数组长度为2的n次幂的时候,不同的key算得得index相同的几率较小,那么数据在数组上分布就比较均匀,也就是说碰撞的几率小,相对的,查询的时候就不用遍历某个位置上的链表,这样查询效率也就较高了。
说到这里,我们再回头看一下hashmap中默认的数组大小是多少,查看源代码可以得知是16,为什么是16,而不是15,也不是20呢,看到上面annegu的解释之后我们就清楚了吧,显然是因为16是2的整数次幂的原因,在小数据量的情况下16比15和20更能减少key之间的碰撞,而加快查询的效率。
所以,在存储大容量数据的时候,最好预先指定hashmap的size为2的整数次幂次方。就算不指定的话,也会以大于且最接近指定值大小的2次幂来初始化的,代码如下(HashMap的构造方法中):
// Find a power of 2 >= initialCapacity int capacity = 1; while (capacity < initialCapacity) capacity <<= 1;
总结:
本文主要描述了HashMap的结构,和hashmap中hash函数的实现,以及该实现的特性,同时描述了hashmap中resize带来性能消耗的根本原因,以及将普通的域模型对象作为key的基本要求。尤其是hash函数的实现,可以说是整个HashMap的精髓所在,只有真正理解了这个hash函数,才可以说对HashMap有了一定的理解。
hashmap为什么容量是2的n次方相关推荐
- HashMap的容量(桶的数量)为什么要是2的n次方
2019独角兽企业重金招聘Python工程师标准>>> HashMap为了存取高效,要尽量较少碰撞,就是要尽量把数据分配均匀,每个链表长度大致相同. 关键就在于把当前数据存放到哪一个 ...
- hashMap的容量(capacity)为什么必须是是2的n次方
HashMap的容量(桶的数量)为什么要是2的n次方 查看hashmap的源码可以发现,如果new一个hashmap对象不指定容量(capacity)的话,hashmap的默认初始化容量是16,也就是 ...
- 被替换的项目不是替换值长度的倍数_面试官,为啥HashMap的长度是2的n次方?
前言 HashMap的主干是一个数组,假设我们有3个键值对dnf:1,cf:2,lol:3,每次放的时候会根据hash函数来确定这个键值对应该放在数组的哪个位置,即index = hash(key) ...
- 关于HashMap初始化容量问题
关于HashMap初始化容量问题 使用阿里云代码规范插件扫描后出现以下提示: hashmap should set a size when initalizing,即hashmap应该在初始化时设置一 ...
- 为什么hashmap的容量必须是2的n次幂
要明白为什么是2的n次幂,这要从hashmap的hash方式说起,hashmap的容量期望就是用来均匀散列存放map中的元素.hashmap根据hash值把元素放到hashmap内部数组的一个位置上. ...
- HashMap最大容量为什么是2的32次方
//默认的桶数组大小 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //极限值(超过这个值就将threshold修改为Intege ...
- hashmap应用场景_Java初学者进阶系列:HashMap的容量与性能
1. HashMap的容量与性能 HashMap的性能受到两个参数的影响:初始化容量和负载因子,下面来详细讲述这几个关键问题. 1.1 Initial Capacity与Load Factor Ini ...
- hashmap 不释放空间_刁难问题,为什么HashMap默认容量为16加载因子为0.75
前言:实际开发中我们大多数都是只能new HashMap<>来存储键值对,很少会去设置初始容量,虽然我们知道他的默认容量是16.但是在面试中,为了体现你个人好学的能力,还是会被经常问到为什 ...
- HashMap的容量与扩容
阅读JDK源码是提高我们技术很好的途径,其中HashMap的设计是非常优秀的,但是其中定义了许多变量,让人头昏目眩,那么这些变量都是什么意思呢 HashMap中的变量 本篇文章主要关注的字段是DEFA ...
最新文章
- bug诞生记——隐蔽的指针偏移计算导致的数据错乱
- vue 不识别svg_vue中引用svg,vue引入svg不显示,vue引用svg配置,vue3.0+ts如何配置svg...
- asp.net ajax中文乱码的解决?2010-01-19 12:06
- android 组件化_Android 组件化路由框架设计(仿Arouter)
- 【BZOJ1206】【HNOI2005】虚拟内存,我也就能写写这种模拟题了
- 一个优秀数据分析师的准则
- SCOM监控APC-UPS不间断电源设备
- login RPi via serial port
- Visual Studio Code下载安装教程
- 数据库(教务管理系统)
- Linux创建和删除目录
- 英雄联盟(LOL)外挂原理(仅供学术交流)
- LC EDA 学习笔记
- 设计原则与思想:设计原则12讲
- 2016.04.03软件更新公告
- python求峰面积_python---matplotlib
- oracle12c命令行安装grid,oracle12c-RAC安装部署之GRID安装-grid设置
- 解决Qt6 Android 开发中 Qtkits 前有黄色感叹号问题
- 微信小程序云开发:基本介绍及云端数据库的使用
- Three.js学习笔记-Lights(灯光)