写在前面:

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  放在第一个格子。

取余操作涉及到底层汇编和运算器电路设计,虽然我本科是电子信息的,但早就把知识还给老师了。

大家只要知道一个结论,就是取余运算没位运算快就行。

经过上面的科普,大家已经知道取余运算没位运算快了(手动狗头脸)。

本着安全第一,效率至上的原则就只能用位运算了。

几个重要因素:

  1. 参与运算的值:hashcode、entry数组长度
  2. 运算方式:位运算 (与&,或|,非~)
  3. 预期结果:有规律可循,起码结果要和取余运算相同。

那就开始设计吧~

(呃....我也没啥好的设计,还是分析下源码吧)

Entry长度-1 = 15;

15的二进制形式

0000-0000 0000-0000 0000-0000 0000-1111

十进制取余算法:

633611702 % 16 = 6

633611702 % 32 = 22

到这为止有三个问题继续解答

  1. 为啥数组长度要是2的n次幂?

  2. 为啥entry数组长度要-1?

  3. 为啥要右移16位进行亦或?

这不是呼之欲出么,呼你妹啊,我到现在还都不知道为啥。

个人理解:

第一个问题

  1. 优化需要:hash & (length -1) 在结果上与 取余算法一致
  2. 符合计算机思维,在计算机中跟数据相关的数值基本都是2的n次

如:MySQL页的大小为16kb

操作系统文件管理系统一次IO读取的数据大小同样为1页(4kb)相当于8个扇区(512bytes )

第二个问题

  1. 数组长度不减1的话,低位都是0,与操作下低位都没法参与运算,而且还有结果越界的情况(如上面的反例)
  2. 减1再与运算,可以使低位都参与运算,增加散列程度。

第三个问题

请各位看官再回去搂一眼最上面的三个例子,右移后再亦或,高位和低位做了混合,在之后的hash & (length-1) 中高位就也参与进运算了,增加了散列程度。

hashmap计算hashcode时为什么要把高位右移16位相关推荐

  1. codeblocks和vscode编译时弹出不支持的16位程序解决方案

    codeblocks和vscode编译时弹出不支持的16位程序解决方案 参考文章: (1)codeblocks和vscode编译时弹出不支持的16位程序解决方案 (2)https://www.cnbl ...

  2. 计算hashCode通用计算公式

    1.java计算公式 @Overridepublic int hashCode() {//设置初始值int result = 17;//假设有效域为: name,age,idCardNo,income ...

  3. HashMap 计算key的hash值方法hash()

    static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >&g ...

  4. 蔚来一面:用Object做hashMap的Key时需要做什么?

    作者 | petterp 来源 | https://blog.csdn.net/petterp/article/details/89043847 先来说一下hashcode()和equals方法吧. ...

  5. java泛型不是计算运行时的数据类型

    2019独角兽企业重金招聘Python工程师标准>>> package com.ada.data.entity;import java.io.Serializable;import ...

  6. Java计算请假时长(根据规则设置去除节假日、休息日、特殊日期)

    首先选择的日期要判断是不是节假日: 这里是写了工具类获取全年的日期信息. dateUtils工具类 某年第一天可以直接拼接 yyyy-01-01 获取节假日方法: public class DateU ...

  7. 计算有效时长的截止工作时间

    最近做项目有个需求,计算有效时长的结束时间,这个结束时间点必须落在工作时间段之内 废话不多说,上代码: 这里解释一下:getduration是主方法:传递四个参数,第一个当前时间,第二个有效时长,第三 ...

  8. igraph 算网络指标_量化投资中,计算技术指标时常见的8个坑

    这是邢不行第 49 期量化小讲堂的分享 作者 | 助教-夏普.邢不行 "我自己计算的指标,跟同花顺给出的指标值差别很大,这是什么情况?" "talib计算的指标和很多主流 ...

  9. python 跳过计算错误_在python中计算分数时如何跳过被0除的错误?

    我正在运行一个很长的CSV文件下面的函数.函数每50行计算列MFE的Z分数.这50行中有一些只包含零,因此在计算Zscore时,程序会停止,因为它不能被零除.如何解决这个问题,而不是停止程序运行打印这 ...

最新文章

  1. Spark 写出MySQL报错,java.sql.BatchUpdateException
  2. 在hue当中设置hive当中数据库的控制权限。
  3. 理解 Word2Vec 之 Skip-Gram 模型【全】
  4. 在MapPath的Path参数中不允许字符'..',解决方法。
  5. 第五届“强网杯”青少年专项赛盛大开赛
  6. 深度学习实验1:pytorch实践与前馈神经网络
  7. python画正方形并涂色_关于python使用cv画矩形并填充颜色同时填充文字
  8. android系统硬件OpenGL 3D移植(二)
  9. 大型网站架构演变和知识体系【转载】
  10. 大数据核心技术是什么 怎么掌握Hadoop知识
  11. 知乎与百度知道竞品分析-用户五要素
  12. TypeScript基础 ts文件的创建与执行
  13. 走进游戏中的美术:游戏美术风格介绍
  14. ros学习记录:Gazebo加载速度慢,长时间停在“Preparing your world”
  15. 微信公众平台开发(92) 多客服(转)
  16. 王小川谈创业必须突破的六大槛:人、产品、渠道、体制、资本、移动
  17. 6种无线通信技术对比(WiFi,Zigbee,蓝牙,Lora,NB-lot,4G)。
  18. dev-tool安装方法(手动安装版)
  19. Codevs 2382 挂缀
  20. FastCGI sent in stderr: PHP message: PHP Fatal error: Call to undefined function __() in

热门文章

  1. ASP服装销售系统设计(论文+答辩PPT+源代码+翻译+开题报告+任务书+实习报告)
  2. 1980莫斯科奥运会歌曲《告别莫斯科》铃声 1980莫斯科奥运会歌...
  3. 怎么证明一个一维函数连续
  4. html+css样式:图片切换-----立体旋转
  5. dp和px,那些不得不吐槽的故事——Android平台图片文字元素单位浅析 (转)
  6. 网络上无限权访问其它计算机,Win7怎么解决电脑无线有限的访问权限?
  7. 如何在公众号上关联小程序?
  8. JVM内存分配机制详解
  9. 最新校园同学跑腿小程序完整源码+有安装教程
  10. Python-基于卷积神经网络斑马线识别分类,准确率高达99%