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 题。
和评分标准对照,你能独立回答到哪一步?
自评会安排下一次复习,不保存你的口述内容。
这道题,你掌握得怎么样?
掌握程度由你主动标记,阅读和收藏不会自动改变状态。