hashmap计算hashcode时为什么要把高位右移16位
写在前面:
1、如有错误请看官斧正。
2、建议把例子复制出去,自己用各种位运算算一下,然后也像我这样把异同处标出来,这样能在自己计算的过程中有更深的领悟。
一、hashmap计算hashcode时为什么要把高位右移16位
有一个hashcode值的二进制形式
key.hashcode()
二进制:0010-0101 1100-0100 0010-0101 1011-0110
十进制:633611702
上面这么写只是为了便于观察,并不遵循任何规范。
key.hashcode() >>> 16 (无符号右移16位)
这个地方是个人理解,不一定准确
亦或运算:不同为1,相同为0 异或运算能更好的保留各部分的特征(变化的地方01都有)
与运算: 有0则0,全1则1 结果偏向于0 (变化的地方都变0了)
或运算: 有1则1,全0则0 结果偏向于1(变化的地方都变1了)
二、再看hashmap是怎么取元素存放位置的
可以看到在取元素存放位置时,1.7和1.8是用的同一方法,
都是hash^(n-1)【哈希值与上entry数组长度-1】
小白提问1:为啥要&entryLength-1呢
抛开上面提到的右移16位问题,你想想,一个对象取完hash值了,它得往entry数组里放吧,但是数组长度又是有限的,不可能一个萝卜一个坑。
以默认初始长度为16为例
想把一个编号大于16的数,在16个格子里找个位置放下,要是你自己设计会咋做呢(不能乱放)
绝大多数人都会选择取余法,就是:编号%格子数
小白举例: 17%16 = 1 放在第一个格子。
取余操作涉及到底层汇编和运算器电路设计,虽然我本科是电子信息的,但早就把知识还给老师了。
大家只要知道一个结论,就是取余运算没位运算快就行。
经过上面的科普,大家已经知道取余运算没位运算快了(手动狗头脸)。
本着安全第一,效率至上的原则就只能用位运算了。
几个重要因素:
- 参与运算的值:hashcode、entry数组长度
- 运算方式:位运算 (与&,或|,非~)
- 预期结果:有规律可循,起码结果要和取余运算相同。
那就开始设计吧~
(呃....我也没啥好的设计,还是分析下源码吧)
Entry长度-1 = 15;
15的二进制形式
0000-0000 0000-0000 0000-0000 0000-1111
十进制取余算法:
633611702 % 16 = 6
633611702 % 32 = 22
到这为止有三个问题继续解答
为啥数组长度要是2的n次幂?
为啥entry数组长度要-1?
为啥要右移16位进行亦或?
这不是呼之欲出么,呼你妹啊,我到现在还都不知道为啥。
个人理解:
第一个问题
- 优化需要:hash & (length -1) 在结果上与 取余算法一致
- 符合计算机思维,在计算机中跟数据相关的数值基本都是2的n次
如:MySQL页的大小为16kb
操作系统文件管理系统一次IO读取的数据大小同样为1页(4kb)相当于8个扇区(512bytes )
第二个问题
- 数组长度不减1的话,低位都是0,与操作下低位都没法参与运算,而且还有结果越界的情况(如上面的反例)
- 减1再与运算,可以使低位都参与运算,增加散列程度。
第三个问题
请各位看官再回去搂一眼最上面的三个例子,右移后再亦或,高位和低位做了混合,在之后的hash & (length-1) 中高位就也参与进运算了,增加了散列程度。
hashmap计算hashcode时为什么要把高位右移16位相关推荐
- codeblocks和vscode编译时弹出不支持的16位程序解决方案
codeblocks和vscode编译时弹出不支持的16位程序解决方案 参考文章: (1)codeblocks和vscode编译时弹出不支持的16位程序解决方案 (2)https://www.cnbl ...
- 计算hashCode通用计算公式
1.java计算公式 @Overridepublic int hashCode() {//设置初始值int result = 17;//假设有效域为: name,age,idCardNo,income ...
- HashMap 计算key的hash值方法hash()
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >&g ...
- 蔚来一面:用Object做hashMap的Key时需要做什么?
作者 | petterp 来源 | https://blog.csdn.net/petterp/article/details/89043847 先来说一下hashcode()和equals方法吧. ...
- java泛型不是计算运行时的数据类型
2019独角兽企业重金招聘Python工程师标准>>> package com.ada.data.entity;import java.io.Serializable;import ...
- Java计算请假时长(根据规则设置去除节假日、休息日、特殊日期)
首先选择的日期要判断是不是节假日: 这里是写了工具类获取全年的日期信息. dateUtils工具类 某年第一天可以直接拼接 yyyy-01-01 获取节假日方法: public class DateU ...
- 计算有效时长的截止工作时间
最近做项目有个需求,计算有效时长的结束时间,这个结束时间点必须落在工作时间段之内 废话不多说,上代码: 这里解释一下:getduration是主方法:传递四个参数,第一个当前时间,第二个有效时长,第三 ...
- igraph 算网络指标_量化投资中,计算技术指标时常见的8个坑
这是邢不行第 49 期量化小讲堂的分享 作者 | 助教-夏普.邢不行 "我自己计算的指标,跟同花顺给出的指标值差别很大,这是什么情况?" "talib计算的指标和很多主流 ...
- python 跳过计算错误_在python中计算分数时如何跳过被0除的错误?
我正在运行一个很长的CSV文件下面的函数.函数每50行计算列MFE的Z分数.这50行中有一些只包含零,因此在计算Zscore时,程序会停止,因为它不能被零除.如何解决这个问题,而不是停止程序运行打印这 ...
最新文章
- Spark 写出MySQL报错,java.sql.BatchUpdateException
- 在hue当中设置hive当中数据库的控制权限。
- 理解 Word2Vec 之 Skip-Gram 模型【全】
- 在MapPath的Path参数中不允许字符'..',解决方法。
- 第五届“强网杯”青少年专项赛盛大开赛
- 深度学习实验1:pytorch实践与前馈神经网络
- python画正方形并涂色_关于python使用cv画矩形并填充颜色同时填充文字
- android系统硬件OpenGL 3D移植(二)
- 大型网站架构演变和知识体系【转载】
- 大数据核心技术是什么 怎么掌握Hadoop知识
- 知乎与百度知道竞品分析-用户五要素
- TypeScript基础 ts文件的创建与执行
- 走进游戏中的美术:游戏美术风格介绍
- ros学习记录:Gazebo加载速度慢,长时间停在“Preparing your world”
- 微信公众平台开发(92) 多客服(转)
- 王小川谈创业必须突破的六大槛:人、产品、渠道、体制、资本、移动
- 6种无线通信技术对比(WiFi,Zigbee,蓝牙,Lora,NB-lot,4G)。
- dev-tool安装方法(手动安装版)
- Codevs 2382 挂缀
- FastCGI sent in stderr: PHP message: PHP Fatal error: Call to undefined function __() in
热门文章
- ASP服装销售系统设计(论文+答辩PPT+源代码+翻译+开题报告+任务书+实习报告)
- 1980莫斯科奥运会歌曲《告别莫斯科》铃声 1980莫斯科奥运会歌...
- 怎么证明一个一维函数连续
- html+css样式:图片切换-----立体旋转
- dp和px,那些不得不吐槽的故事——Android平台图片文字元素单位浅析 (转)
- 网络上无限权访问其它计算机,Win7怎么解决电脑无线有限的访问权限?
- 如何在公众号上关联小程序?
- JVM内存分配机制详解
- 最新校园同学跑腿小程序完整源码+有安装教程
- Python-基于卷积神经网络斑马线识别分类,准确率高达99%