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

相关推荐
编程大师哥3 分钟前
Java web
java·开发语言·前端
小棠师姐6 分钟前
随机森林原理与实战:如何解决过拟合问题?
算法·机器学习·随机森林算法·python实战·过拟合解决
电商API_180079052478 分钟前
大麦网API实战指南:关键字搜索与详情数据获取全解析
java·大数据·前端·人工智能·spring·网络爬虫
dasi02279 分钟前
Java 趣闻
java
C雨后彩虹10 分钟前
synchronized高频考点模拟面试过程
java·面试·多线程·并发·lock
JAVA+C语言11 分钟前
Java ThreadLocal 的原理
java·开发语言·python
lkbhua莱克瓦2418 分钟前
进阶-SQL优化
java·数据库·sql·mysql·oracle
行稳方能走远26 分钟前
Android java 学习笔记 1
android·java
kaico201827 分钟前
多线程与微服务下的事务
java·微服务·架构
zhglhy27 分钟前
QLExpress Java动态脚本引擎使用指南
java