java: Java8以后hashmap扩容后根据高位确定元素新位置

一、举例说明

例子:

  • hashmap原容量 oldCap = 16(二进制:0001 0000

  • hashmap新容量 newCap = 32

  • hash1 = 33,hash2 = 17

明确以下事项前提

  1. hash值,由hash函数决定,扩容不影响hash值

  2. 新位置(也就是桶下标),受扩容影响,可能变,可能不变,如何判断新位置就是本文要讲的内容

  3. 位置(桶下标)的计算 index = hash & (cap - 1),其中cap为2的n次方

项目 不移动示例(hash1 = 33) 移动示例(hash2 = 17)
hash(十进制) 33 17
hash(二进制) 0010 0001 0001 0001
oldCap(二进制) 0001 0000 0001 0000
原桶下标 = hash & (****oldcap - 1) 33 & 15 = 1 17 & 15 = 1
原桶下标(二进制) 0010 0001 & 0000 1111 = 0000 0001 0001 0001 & 0000 1111 = 0000 0001
hash & oldcap 33 & 16 = 0 17 & 16 = 16
hash & oldcap(二进制) 0010 0001 & 0001 0000 = 0000 0000 0001 0001 & 0001 0000 = 0001 0000
高位 0 1
是否移动 ==0 不移动 != 0 移动
新桶下标 = hash & (32 - 1) 33 & 31 = 1 17 & 31 = 17 = 1+ 16
新桶下标(二进制) 0010 0001 & 0001 1111 = 0000 0001 0001 0001 & 0001 1111 = 0001 0001

二、解释

2.1 什么是高位?

高位就是数字的二进制最左边 那个位,比如:

16,二进制为10000,高位就是5;

64,二进制为1000000,高位就是7;

2.2 java8以后,HashMap 扩容时如何确定某个元素的新位置?

hash值老数组长度oldcap 进行按位与运算 ,得到的结果 ,看它是否为0:

为0,则 不移动

不为0,则 新位置=老位置+老数组长度

用公式描述:

或者也可以看高位,二者本质相同

hash值老数组长度oldcap 进行按位与运算 ,得到的结果 ,看它"对应老数组高位 "是否为0:

为0,则 不移动

为1,则 新位置=老位置+老数组长度

表格,红色字体那里标的很清晰

三、源码解析

java 复制代码
if ((e.hash & oldCap) == 0) {
    // 高位为 0,不移动
    if (loTail == null)
        loHead = e;
    else
        loTail.next = e;
    loTail = e;
} else {
    // 高位为 1,移动到 oldIndex + oldCap
    if (hiTail == null)
        hiHead = e;
    else
        hiTail.next = e;
    hiTail = e;
}

3.1 这段代码在做什么

判断 hash 在"扩容新增的那一位"上是 0 还是 1


两种结果,对应两种新索引

情况一:高位 = 0(不移动)

(e.hash & oldCap) == 0

  • 新索引 = 旧索引

  • 仍然落在原桶位置

数学等价于:

hash & (newCap - 1) == hash & (oldCap - 1)


情况二:高位 = 1(发生移动)

(e.hash & oldCap) != 0

  • 新索引 = 旧索引 + oldCap

也就是:

newIndex = oldIndex + oldCap

相关推荐
CoderCodingNo2 小时前
【NOIP】2011真题解析 luogu-P1003 铺地毯 | GESP三、四级以上可练习
算法
翊谦2 小时前
Java Agent开发 Milvus 向量数据库安装
java·数据库·milvus
晓晓hh3 小时前
JavaSE学习——迭代器
java·开发语言·学习
iFlyCai3 小时前
C语言中的指针
c语言·数据结构·算法
查古穆3 小时前
栈-有效的括号
java·数据结构·算法
再一次等风来3 小时前
近场声全息(NAH)仿真实现:从阵列实值信号到波数域重建
算法·matlab·信号处理·近场声全息·nah
汀、人工智能3 小时前
16 - 高级特性
数据结构·算法·数据库架构·图论·16 - 高级特性
大熊背3 小时前
利用ISP离线模式进行分块LSC校正的方法
人工智能·算法·机器学习
Java面试题总结3 小时前
Spring - Bean 生命周期
java·spring·rpc
硅基诗人3 小时前
每日一道面试题 10:synchronized 与 ReentrantLock 的核心区别及生产环境如何选型?
java