Java中String.hashCode()选用31作为乘数,因其是兼顾低冲突率、高效位运算优化((i

Java 中 String.hashCode() 使用 31 作为乘数,并非偶然,而是综合考虑冲突率、计算效率和数值稳定性后的务实选择。
降低哈希冲突概率
31 是一个质数,能有效减少因字符组合相似导致的哈希值重复。比如两个字符串仅首字符不同(如 "abc" 和 "xbc"),由于高位权重高(31n−1),微小变化会显著拉大哈希值差距;而若用合数(如 10),末位字符对结果影响可能被放大或抵消,容易造成分布偏斜。实测表明,在五万多个英文单词上,31、37、41 等质数的冲突数都低于 7 次,31 在其中表现均衡。
支持高效位运算优化
JVM 可将 31 × i 自动优化为 (i : - 左移 5 位等价于乘以 32 - 再减去自身,就得到乘以 31 的结果 这种替换避免了耗时的乘法指令,尤其在早期 JVM 中提升明显。现代虚拟机仍保留该优化路径,且 31 是满足该条件的最小奇质数之一(下一个满足 i 形式的奇质数是 63,但 63 不是质数)。
兼顾数值范围与溢出控制
31 是“不大不小”的折中: - 太小(如 2 或 3)会导致哈希值集中在低位,冲突上升 - 太大(如 101)易使 int 类型(32 位有符号)频繁溢出,削弱高位区分度 - 31 占用 5 位二进制,乘法过程中信息丢失风险较低,同时保证足够大的取值空间,让不同字符串更大概率映射到不同桶中。
符合散列设计惯例
《Effective Java》明确指出:使用奇质数可避免偶数乘法带来的低位清零风险(例如 ×2 相当于
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











