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

相关推荐
光依旧11 分钟前
MCP实战手记系列(五):让工具返回一个能点的界面(文末附github源码链接)
java·spring ai·前端集成·mcp·mcp apps
APIshop16 分钟前
淘宝选品接口实战:从召回、详情、佣金到转链的 Java 接入笔记
java
泡茶喝茶写代码32 分钟前
量化数据进阶:多维实战篇(第 11 篇):历史涨跌停价:涨跌停序列与止损线测算
java·python·股票数据api·股票数据·股票数据api接口·股票api数据接口·股票量化数据api
景熙552344 分钟前
单体项目编写思路和落地形式
java·开发语言
Ivanqhz1 小时前
Slope One 算法详解:与矩阵分解、共现矩阵的异同
java·服务器·网络·人工智能·深度学习
别动我齐刘海1 小时前
ROS2 Jazzy + C++ 实战路线——进阶学习3
c++·人工智能·vscode·python·算法·机器学习·机器人
Bs_MoneyMagnet1 小时前
基于springboot+vue的非遗物质文化遗产系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
万物智能1 小时前
波形发生AD9833模块配置—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
java
zhangfeng11331 小时前
《从“人工适配“到“智能生成“:KernelSwift 跨国产芯片算子迁移全栈方案解读》 —— 强调范式跃迁和跨硬件属性,适合偏架构分析的写法
人工智能·算法·华为·ai编程·npu
0+1111 小时前
算法 --滑动窗口
c++·算法·leetcode