HashMap扩容时的rehash方法中(e.hash & oldCap) == 0算法推导_Dylanu的博客-程序员秘密

技术标签: ThinkInProgramming  Java  算法  java  链表  foundation  数据结构  

PS:由于文档是我在本地编写好之后再复制过来的,有些文本格式没能完整的体现,故提供下述图片,供大家阅览,以便有更好的阅读体验:
在这里插入图片描述

HashMap在扩容时,需要先创建一个新数组,然后再将旧数组中的数据转移到新数组上来
此时,旧数组上的数据就会根据(e.hash & oldCap) 是否等于0这个算法,被很巧妙地分为2类:
① 等于0时,则将该头节点放到新数组时的索引位置等于其在旧数组时的索引位置,记为低位区链表lo开头-low;
② 不等于0时,则将该头节点放到新数组时的索引位置等于其在旧数组时的索引位置再加上旧数组长度,记为高位区链表hi开头high.
具体,详见下述的算法推导解析:
算法:
(e.hash & oldCap)=0
前提:
 e.hash代表的是旧数组中节点或元素或数据e的hash值,该hash值是根据key确定过的:(key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16) ;
 oldCap为旧数组的数组长度,是2的n次幂的整数。即e.hash&2^n=0

推导过程1(e.hash & oldCap)=0:

  1. 因为oldCap是2的n次幂的整数,其二进制表达为1个1后面跟n个0:1000…0,若想要e.hash&oldCap的结果为0,则e.hash的二进制形式中与对应oldCap的二进制的1的位置一定为0,其他位置的可以随意,这样即可保证结果为0;
  2. 假设:
    oldCap= 2 ^ 3 =8 = 1000
    则e.hash可以是 0101

e.hash&oldCap 0000=0
3. (2oldCap -1)=2 ^ 4-1=01111,其二进制位数比oldCap多一位,但多的这一位是0,其余都是1(其低三位肯定也是1);(oldCap-1)=2 ^ 3-1=0111,其二进制位数与oldCap相同,且其低3位的值都是1。故(2oldCap-1)和(oldCap -1)两者与只有4位且首位为0的e.hash=0101计算时,其实只有低3位真正能影响计算结果,而两者的低3位相同,都是111;
4. 故在前提条件下,(2oldCap-1)和(oldCap -1)两者与e.hash进行&运算之后的结果一样:
(2oldCap -1)=2 ^ 4-1= 01111 (oldCap-1)=2 ^ 3-1= 0111
e.hash 0101 e.hash 0101


e.hash&oldCap 00101=5 e.hash&oldCap 0101=5
5. 而(oldCap -1) &e.hash恰巧代表的就是e元素在旧数组中的索引位置;
而(2oldCap -1) &e.hash则代表的就是e元素在旧数组长度扩容2倍后的新数组里的索引位置
6. 综上,可得出满足e.hash&oldCap=0的元素,其在新旧数组中的索引位置不变;

推导过程2(e.hash & oldCap)不等于0:

  1. 因为oldCap是2的n次幂的整数,其二进制表达为1个1后面跟n个0:1000…0,若想要e.hash&oldCap的结果不为0,则e.hash的二进制形式中与对应oldCap的二进制的1的位置一定不为0,其他位置的可以随意,这样即可保证结果不为0;
  2. 假设:
    oldCap= 2 ^ 3 =8 = 1000
    则e.hash可以是 1101

e.hash&oldCap 1000=13
3. (2oldCap -1)=2 ^ 4-1=01111,其二进制位数比oldCap多一位,但多的这一位是0,其余都是1(其低三位肯定也是1,其从左到右数的第4位为1);(oldCap-1)=2 ^ 3-1=0111,其二进制位数与oldCap相同,且其低3位的值都是1, 其从左到右数的第4位为0,。故(2oldCap-1)和(oldCap -1)两者与只有4位且首位为1的e.hash=1101计算时,其实也只有从左到右数的第4位(0)真正能影响计算结果,因为低3位完全一样都是1;
4. 故在前提条件下,(2oldCap-1)和(oldCap -1)两者与e.hash进行&运算后结果相差了oldCap:
(2oldCap -1)=2^4-1= 01111 ( oldCap - 1 ) =2 ^ 3-1= 0111
e.hash 1101 e.hash 1101


(2oldCap -1)& e.hash 01101=8+5 (2oldCap -1)&e.hash 0101=5
5. 而(oldCap -1) &e.hash恰巧代表的就是e元素在旧数组中的索引位置;
而(2oldCap -1) &e.hash则代表的就是e元素在旧数组长度扩容2倍后的新数组里的索引位置
6. 综上,可得出满足e.hash&oldCap不等于0的元素,其在新数组中的索引位置是其在旧数组中索引位置的基础上再加上旧数组长度个偏移量。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010425839/article/details/106620440

智能推荐

最新版FatFs R0.14移植到STM32F4工程中所遇问题汇总_stm32 fatfs 文件丢失_zhizw的博客-程序员秘密

因最近赶论文,先作小记,以后有时间再整理。。。之前在STM32F4工程中将数据直接保存在SD卡上,没有文件系统,虽然可以充分利用SD卡的空间,但不得不借助WinHex等工具才能读取出数据,保存成可识别的文本文件或二进制文件,然后再做数据解析、处理,这个过程非常麻烦,且对于用户来说不具可操作性。因此,考虑在工程中使用FatFs,牺牲一部分SD容量换取后续处理数据的便捷,也是值得的!学习了正点...

2019年华为开发者大会_如何在2019年及以后成为自由开发者的品牌_cumian8165的博客-程序员秘密

2019年华为开发者大会The web development industry is booming. Web开发行业正在蓬勃发展 。 This may be advantageous for freelancers, but it also has its negatives. 这对于自由职业者可能是有利的,但也有其负面影响。 What negatives? 什么负面因素? When i...

如何正确理解《中医医院信息化建设基本规范》和《中医医院信息系统基本功能规范》_computersoftware的博客-程序员秘密

《中医医院信息化建设基本规范》(下称《建设规范》)和《中医医院信息系统基本功能规范》(下称《功能规范》)是国家中医药管理局2011年10月制定印发的,规范提出以医院管理和中医电子病历为重点,构建中医药特色鲜明、技术平台先进、服务管理规范、系统安全高效的现代化中医医院。        《功能规范》主要分为基础功能与医院信息集成平台、临床服务部分和医院管理部分。《功能规范》指出,中医医院信息系

跟我来学小程序(一)项目目录和项目文件介绍_pages目录的作用_ShrMuscles的博客-程序员秘密

大家好,我是一个爱举铁的程序员Shr。 本篇文件介绍小程序项目的目录和项目文件。 源码地址:https://github.com/ShrMus/wechat_xcx/tree/master/demo_20180603 一、新建项目打开微信web开发者工具,选择小程序项目,由于没有新建过项目,打开之后是下图的界面,选择项目目录,填写注册之后获得的AppID,填写项目名...

Unity用键盘控制物体左右旋转前后移动的c#脚本_猿憨憨的博客-程序员秘密

using System.Collections;using System.Collections.Generic;using UnityEngine;public class CubeScript : MonoBehaviour {void Start () {}void Update () {        float Hor = Input.Get

敌兵布阵(树状数组 ) HDU 1166_敌兵布阵(树状数组)【hdu1166】_SY_Pistachio的博客-程序员秘密

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 123593    Accepted Submission(s): 51789   Problem Description C国的死对头A国...

随便推点

JDOM_iteye_17076的博客-程序员秘密

JDOM(Java Document Object Model):java文档对象模型.http://www.jdom.orgDOM被设计为用于完成几乎所有的XML操作任务,同时它又是与语言无关,这就导致DOM的API庞大而复杂。为了给JAVA程序员提供一套简单易用的操作XML的API,java技术专家Jason Hunter和Brett McLaughlin创建了JDOM。JDOM利用J...

【周阳-Redis】【08】Redis的Master-Slave_redis salves=4_lpruoyu的博客-程序员秘密

持续学习&持续更新中…守破离【周阳-Redis】【08】Redis的Master-SlaveRedis的Master-Slave单机多Redis实例搭建环境怎么玩常用三招一主多仆反客为主薪火相传(去中心化)哨兵模式(sentinel)是什么怎么玩主从复制原理主从复制缺点参考Redis的Master-Slave行话:也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制Master以写为主,Slave以读为主可以实现的主要功能:读写.

Spring mvc 接入 shardingsphere5.0.0 自定义表分片规则_shardingsphere5.0自定义分片_wangzy-nice的博客-程序员秘密

背景最近在搞数据迁移,之前存储的介质为mongo,集团层面在推动mongo下线,所以迁移到mySql是主流趋势,mongo目前共6分片,总数大概40亿左右,mySql承接的话,设计为32个库,每个库128个表。数据库的分片,中间件团队已经做了,我们需要处理的是路由到表这块的处理前置官方资料https://shardingsphere.apache.org/document/ 选择5.0.0版本进行阅读使用Spring boot 能很快结束开发,使用Spring mvc实属无奈,但是旧系统升级重构

Netty_Android 使用netty与服务器保持长连接腾讯_张俨的博客-程序员秘密

Netty_Android项目地址:https://github.com/zhangYanGitHub/Netty_Demo采用netty-4.1.16.Final 于服务器保持长连接进行通讯主要思路为: 开启一个service 初始化Netty连接service 类private NetworkReceiver receiver; public static...

el-tooltip内容换行,很简单,加一行代码_el-tooltip换行_阿林阿林的博客-程序员秘密

项目需求其实很常见,就是平时的问号提示语就是这个问号,但是没有换行,视觉效果太差了如图:代码:<el-tooltip class="item" effect="dark" content="创建创意时从视频中自动抽取多帧图片优选生成封面,本方案无需手动上传图片" placement="top"> <i class="el-icon-question smartTip"></i></el-tooltip>修改..

C++学习记录002——创建C++动态链接库封装类(函数)给MFC调用(初学者详细步骤)_vc动态链接库按照类的形式封装_SYW#的博客-程序员秘密

工具:VS2019项目:MFC调用C++动态链接库的项目的DLL一、创建DLL如图,选好要创建的项目取个名字,选好地址,点击“创建”在解决方案资源管理器中,右击“头文件”——>"添加“——>"新建项",选择”头文件(.h)"——>取个名字——>点击“添加”...

推荐文章

热门文章

相关标签