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

相关推荐
用户1563068103512 小时前
Day01 | Java 基础(Java SE)
java
行者全栈架构师4 小时前
Maven dependency:tree 的 8 个高级用法
java·后端
行者全栈架构师8 小时前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
令人头秃的代码0_08 小时前
mac(m5)平台编译openjdk
java
JieE21217 小时前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack201 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树1 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
唐青枫1 天前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
一个做软件开发的牛马1 天前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户3721574261351 天前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java