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 的倍数相关推荐

  1. hashmap value占用空间大小_【Java集合框架002】原理层面:HashMap全解析

    一.前言 二.HashMap 2.1 HashMap数据结构 + HashMap线程不安全 + 哈希冲突 2.1.1 HashMap数据结构 学习的时候,先整体后细节,HashMap整体结构是 底层数 ...

  2. HashMap的大小为什么必须是2的倍数

    HashMap如何保证大小一定是2的倍数 了解HashMap的都知道,HashMap的大小必须是2的倍数,通过调用tableSizeFor方法来保证HashMap的大小为2的次方,如果你在构造函数中传 ...

  3. 合理设置 HashMap 初始值大小

    在 Java 开发中少不了使用 HashMap,但是通常使用 HashMap 时就是简单的进行 new 一下就可以开始使用了.比如这样: HashMap<String, Object> p ...

  4. HashMap之数组下标计算

    HashMap之数组下标计算 前提 loadFactor capacity threshold put时,数组下标计算 hash函数 putVal函数 核心计算 扩容时,下标的重置计算 前提 Hash ...

  5. 【C 语言】数组 ( 指针退化验证 | 计算数组大小 | #define LENGTH(array) (sizeof(array) / sizeof(*array)) )

    文章目录 一.指针退化验证 二.完整代码示例 一.指针退化验证 nnn 维数组 作为 函数参数 , 会退化为 指针 , 注意这里只有 最高维 第 nnn 维 会 退化为指针 , 该指针指向 若干 n− ...

  6. 线段树的数组大小下限及证明

    线段树的数组大小下限及证明 手动博客搬家: 本文发表于20170820 20:23:52, 原地址https://blog.csdn.net/suncongbo/article/details/774 ...

  7. C语言高级编程:sizeof计算数组大小需要注意的问题

    测试平台:64位 X86 Ubuntu 1. 代码: #include <stdio.h>void main(void) {char a[20];printf("sizeof(a ...

  8. HashMap中数组初始化的秘密

    2019独角兽企业重金招聘Python工程师标准>>> 我们知道,在新建一个HashMap对象时,无论传的initialCapacity参数值为多少,最总HashMap中数组的长度始 ...

  9. 数组超过预设的最大数组大小_工作表数组大小的扩展及意义

    朋友们好,今日给大家继续讲解VBA数组与字典解决方案的第17讲,数组大小的扩充问题.这一讲的内容相对比较简单,在之前的章节中讲了数组与数组的计算规律,也是利用了数组的扩展原理. 其实,两个数组计算时, ...

  10. 数组名不等于指针---sizeof()函数求数组大小错误问题

    前言: 今天在项目中需要求采样点的数量并且遍历,采样点用数组存储,自定义了一个函数想要用sizeof求其长度,然后遍历,结果失败了,查阅之后发现以下问题: 在main函数中,sizeof是可以正常工作 ...

最新文章

  1. 关于 Rocksdb 性能分析 需要知道的一些“小技巧“ -- perf_context的“内功” ,systemtap、perf、 ftrace的颜值
  2. mysql latid1_【转】mysql触发器的实战经验(触发器执行失败,sql会回滚吗) | 学步园...
  3. mysql表大小限制_技术分享 | 在磁盘上查找 MySQL 表的大小
  4. 调试一个C#研究生管理信息系统源码
  5. 孙悟空!登上 Nature !
  6. Android实例-手机安全卫士(三十六)-根据Service是否开启确定CheckBox选中状态
  7. 系统无法执行指定的程序。_使用Rust编写操作系统(一):独立式可执行程序
  8. 刚入职新公司做一些什么贡献_如果您有全职工作,如何为Kubernetes做贡献
  9. selenium使用浏览器隐私模式加载网站
  10. java 正则表达式-忽略大小写与多行匹配
  11. exfat最佳单元大小_ICLR2019最佳论文!神经网络子网络压缩10倍,精确度还能保持不变...
  12. pymysql操作MySQL数据库表-----爬虫豆瓣top250电影并存入数据库
  13. 零散专题32 生成PDF
  14. android点击不灵敏,华为手机触摸屏没反应怎么办?解决手机触摸屏时灵时不灵的办法...
  15. ArcEngine创建平头缓冲区的方法
  16. 右键添加显示隐藏文件夹功能
  17. java web树形图查询_Javaweb生成族谱树形图
  18. html 点击增加样式,js点击添加css样式 css添加jq点击事件 JavaScript点击增加css样式...
  19. java strace_用strace排查故障的5种简单方法(每日一译)
  20. 吉大20计算机组成原理大作业,吉大20年9月课程计算机组成原理答案假期吖在线...

热门文章

  1. 面向对象编程时,十条原则:
  2. java.lang.IllegalArgumentException: No enum constant org.apache.ws.commons.schema.XmlSchemaForm.
  3. c#之有参和无参构造函数,扩展方法
  4. Java程序设计之扑克牌
  5. 案例研究–亚马逊服务中断,数据库崩溃–我们恢复数据库且无数据损失
  6. 文件上传------c#
  7. 063 模块的四种形式
  8. 小明买了一箱鸡蛋,假设有n个,可以一天吃1个,也可以一天吃2个,请问有多 少种方法可以吃完?...
  9. 黑马程序员 oc中的类与对象
  10. C#获取屏幕大小或任务栏大小