Java 后端面试题库 / 全部题解免费阅读理解原理,有条理地回答

HashMap 为什么不直接把 hashCode 当数组下标?

先说出你的答案

定义边界、关键机制、一个反例;P8题再补容量、失败与验证。

查看完整题解

参考回答

直接回答

hashCode 的取值范围很大,还可能是负数,而桶数组只有有限长度,不能直接作为下标。OpenJDK 21 先混合高低位,再用容量减一与哈希做按位与,把结果限制在合法范围。哈希值用于分区,不是对象在内存中的地址,也不需要全局唯一。

讲清原理

桶数为二次幂时,(n - 1) & hash 可以选取相应低位,得到 0 到 n-1 的下标。若直接只看原 hashCode 的低位,高位的差异就难以参与当前分布,所以实现先用 h ^ (h >>> 16) 扰动。

容量翻倍时只多看一个二进制位,旧桶便可分成两组;但完全相同的混合哈希仍无法被拆开。不能把“扰动”理解为消除所有碰撞,也不要用 abs(hashCode) 当作万能修复,最小 int 的绝对值仍是负数。

扩容为两倍时,旧桶按新增的一个二进制位分成两组
扩容为两倍时,旧桶按新增的一个二进制位分成两组

例子与易错点

Java 21 的 main 片段:

int h = -123;
int hash = h ^ (h >>> 16);
int index = (16 - 1) & hash;
System.out.println(index);
System.out.println(Math.abs(Integer.MIN_VALUE) < 0);

输出 10、true。上式是所核对实现的说明,不应让业务代码复制 HashMap 内部索引公式来操控容器。公开 API 才是调用方的依赖边界。

相关题:第 2 题、第 14 题、第 41 题、第 42 题。

这道题,你掌握得怎么样?

掌握程度由你主动标记,阅读和收藏不会自动改变状态。