发布于2026-07-04 阅读(0)
扫一扫,手机访问
先捞干的——哈希表底层用 2 的幂次做桶容量,取模其实靠的是位与运算(hash & (capacity - 1))。如果你乘数本身和小因子有勾连,比如 32 = 2⁵,那它和 2ⁿ 的桶长就有公共因子,后果就是:一部分比特位直接被“吃掉”,根本进不了索引计算,大量相似的对象就会被赶到同一个桶里,冲突率就上来了。
31 是质数,和 2 的幂天然互质,这就保证了输入的每个字节、每个字段对最终桶索引的影响都是独立且不可简化的,打散了取模阶段潜在的聚集惯性。
那么,为什么偏偏是 31,不是 29、37,或者更大的质数?
它其实卡在了一个极其精妙的平衡点上:
当然,31 还有一个让 JVM 爱不释手的特性——它等于 2⁵ 减 1。这意味在 HotSpot 编译器的 JIT 阶段,31 * h 可以被自动优化成 (h 左移 5 位) - h。左移和减法都是单时钟周期指令,比通用乘法器快得多,实测能提速 15% 左右。而且这优化是 JVM 在后台自动做的,开发者只需老老实实写 31 * h + c,省心又高效。
那实际写 hashCode 时,到底该怎么用好 31?

不是机械套公式就行,得结合场景做合理延伸:
int result = 1,然后逐字段累积:result = 31 * result + (field == null ? 0 : field.hashCode())。private final int hashCode,hashCode() 直接返回它,省掉每次遍历的开销。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8