hashmap初试数组大小为什么一定要是2 的倍数
1、在hashmap 的底层源码中,首先会计算一个 key 的 hash 码,比如计算一个字符串 "1".hashcode(); 会得到 hashcode 的大小为 49,但是 hashmap 默认数组的大小是 16,所以这样肯定是不能存到数组里面的,会越界
2、需要再次通过一个 hash 函数(这个hash 函数是自己定义的)来得到一个 hash 值,在 hashmap 的底层,这个 hash 函数是用 hashcode 的低 16 位与 高16 位进行的一次异或运算如下:
为什么要进行这一步的运算呢?看下面:
这就是HashMap的高明之处。先看个例子,一个十进制数32768(二进制1000 0000 0000 0000),经过上述公式运算之后的结果是35080(二进制1000 1001 0000 1000)。看出来了吗?或许这样还看不出什么,再举个数字61440(二进制1111 0000 0000 0000),运算结果是65263(二进制1111 1110 1110 1111),现在应该很明显了,它的目的是让“1”变的均匀一点,散列的本意就是要尽量均匀分布。那这样有什么意义呢?看第3步。
3、 得到h之后,把h与HashMap的承载量(HashMap的默认承载量length是16,可以自动变长。在构造HashMap的时候也可以指定一个长 度。这个承载量就是上图所描述的数组的长度。)进行逻辑与运算,即 h & (length-1),这样得到的结果就是一个比length小的正数,我们把这个值叫做index。其实这个index就是索引将要插入的值在数组中的 位置。第2步那个算法的意义就是希望能够得出均匀的index,这是HashTable的改进,HashTable中的算法只是把key的 hashcode与length相除取余,即hash % length,这样有可能会造成index分布不均匀。还有一点需要说明,HashMap的键可以为null,它的值是放在数组的第一个位置。
3、得到 hash 值之后,再与数组的长度-1(length-1)进行一次与运算,因为如果数组的长度是 2 的倍数,那么length-1 的二进制一定是 ...00001111...这种形式,也就是前面一定都是 0,后面全是1,那么再与 hash 值进行与运算的时候,结果一定是在原来数组大小的范围内,比如默认数组大小16-1=15 的二进制为: 00000000 00000000 00000000 00001111,某 key 的hash 值为:11010010 00000001 10010000 00100100,那么与上面做与运算的时候,值会对后面的四位进行运算,肯定会落在0~15 的范围内,假如不是 2 的倍数,那么 length-1 的二进制后面就不可能全是 1,做与运算的时候就会造成空间浪费
hashmap初试数组大小为什么一定要是2 的倍数相关推荐
- hashmap value占用空间大小_【Java集合框架002】原理层面:HashMap全解析
一.前言 二.HashMap 2.1 HashMap数据结构 + HashMap线程不安全 + 哈希冲突 2.1.1 HashMap数据结构 学习的时候,先整体后细节,HashMap整体结构是 底层数 ...
- HashMap的大小为什么必须是2的倍数
HashMap如何保证大小一定是2的倍数 了解HashMap的都知道,HashMap的大小必须是2的倍数,通过调用tableSizeFor方法来保证HashMap的大小为2的次方,如果你在构造函数中传 ...
- 合理设置 HashMap 初始值大小
在 Java 开发中少不了使用 HashMap,但是通常使用 HashMap 时就是简单的进行 new 一下就可以开始使用了.比如这样: HashMap<String, Object> p ...
- HashMap之数组下标计算
HashMap之数组下标计算 前提 loadFactor capacity threshold put时,数组下标计算 hash函数 putVal函数 核心计算 扩容时,下标的重置计算 前提 Hash ...
- 【C 语言】数组 ( 指针退化验证 | 计算数组大小 | #define LENGTH(array) (sizeof(array) / sizeof(*array)) )
文章目录 一.指针退化验证 二.完整代码示例 一.指针退化验证 nnn 维数组 作为 函数参数 , 会退化为 指针 , 注意这里只有 最高维 第 nnn 维 会 退化为指针 , 该指针指向 若干 n− ...
- 线段树的数组大小下限及证明
线段树的数组大小下限及证明 手动博客搬家: 本文发表于20170820 20:23:52, 原地址https://blog.csdn.net/suncongbo/article/details/774 ...
- C语言高级编程:sizeof计算数组大小需要注意的问题
测试平台:64位 X86 Ubuntu 1. 代码: #include <stdio.h>void main(void) {char a[20];printf("sizeof(a ...
- HashMap中数组初始化的秘密
2019独角兽企业重金招聘Python工程师标准>>> 我们知道,在新建一个HashMap对象时,无论传的initialCapacity参数值为多少,最总HashMap中数组的长度始 ...
- 数组超过预设的最大数组大小_工作表数组大小的扩展及意义
朋友们好,今日给大家继续讲解VBA数组与字典解决方案的第17讲,数组大小的扩充问题.这一讲的内容相对比较简单,在之前的章节中讲了数组与数组的计算规律,也是利用了数组的扩展原理. 其实,两个数组计算时, ...
- 数组名不等于指针---sizeof()函数求数组大小错误问题
前言: 今天在项目中需要求采样点的数量并且遍历,采样点用数组存储,自定义了一个函数想要用sizeof求其长度,然后遍历,结果失败了,查阅之后发现以下问题: 在main函数中,sizeof是可以正常工作 ...
最新文章
- 关于 Rocksdb 性能分析 需要知道的一些“小技巧“ -- perf_context的“内功” ,systemtap、perf、 ftrace的颜值
- mysql latid1_【转】mysql触发器的实战经验(触发器执行失败,sql会回滚吗) | 学步园...
- mysql表大小限制_技术分享 | 在磁盘上查找 MySQL 表的大小
- 调试一个C#研究生管理信息系统源码
- 孙悟空!登上 Nature !
- Android实例-手机安全卫士(三十六)-根据Service是否开启确定CheckBox选中状态
- 系统无法执行指定的程序。_使用Rust编写操作系统(一):独立式可执行程序
- 刚入职新公司做一些什么贡献_如果您有全职工作,如何为Kubernetes做贡献
- selenium使用浏览器隐私模式加载网站
- java 正则表达式-忽略大小写与多行匹配
- exfat最佳单元大小_ICLR2019最佳论文!神经网络子网络压缩10倍,精确度还能保持不变...
- pymysql操作MySQL数据库表-----爬虫豆瓣top250电影并存入数据库
- 零散专题32 生成PDF
- android点击不灵敏,华为手机触摸屏没反应怎么办?解决手机触摸屏时灵时不灵的办法...
- ArcEngine创建平头缓冲区的方法
- 右键添加显示隐藏文件夹功能
- java web树形图查询_Javaweb生成族谱树形图
- html 点击增加样式,js点击添加css样式 css添加jq点击事件 JavaScript点击增加css样式...
- java strace_用strace排查故障的5种简单方法(每日一译)
- 吉大20计算机组成原理大作业,吉大20年9月课程计算机组成原理答案假期吖在线...
热门文章
- 面向对象编程时,十条原则:
- java.lang.IllegalArgumentException: No enum constant org.apache.ws.commons.schema.XmlSchemaForm.
- c#之有参和无参构造函数,扩展方法
- Java程序设计之扑克牌
- 案例研究–亚马逊服务中断,数据库崩溃–我们恢复数据库且无数据损失
- 文件上传------c#
- 063 模块的四种形式
- 小明买了一箱鸡蛋,假设有n个,可以一天吃1个,也可以一天吃2个,请问有多 少种方法可以吃完?...
- 黑马程序员 oc中的类与对象
- C#获取屏幕大小或任务栏大小