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

相关推荐
Zane19945 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
噢,我明白了6 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品6 小时前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘6 小时前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
Java内核笔记6 小时前
告别十亿美元的错误 : Spring Boot 4 空安全 (JSpecify) 实战
java·spring boot·后端
烬羽6 小时前
递归老写崩?一个"退回"公式,把回溯题变成填空题
javascript·深度学习·算法
糖果店的幽灵6 小时前
langgraph的 MessagesState 解读
java·开发语言·人工智能·windows·langgraph
闪电悠米6 小时前
力扣hot100-41.缺失的第一个正数-原地哈希详解
数据结构·算法·哈希算法
星空露珠7 小时前
28种颜色对应名称,
开发语言·数据库·算法·游戏·lua
极光代码工作室8 小时前
基于SpringBoot的在线博客系统
java·springboot·web开发·后端开发