Java中String.hashCode()选用31作为乘数,因其是兼顾数学特性、硬件效率和工程实践的优选质数:既避免小质数导致低位信息淹没,又防止大质数引发int溢出,且支持JVM将31*h优化为(h<<5)-h。

Java 中 String.hashCode() 选用 31 作为乘数,不是随意定的,而是兼顾数学特性、硬件效率和工程实践后的综合优选。
31 是个“刚刚好”的质数
质数能降低哈希值重复的概率,因为用质数参与运算后,不同字符串更难凑出相同结果。但质数不能太小(如 2、3),否则容易导致低位信息被快速淹没,哈希值集中在小范围;也不能太大(如 97、101),否则多次乘加后极易超出 int 的 32 位范围,造成溢出失真。31 在质数序列中属于“不大不小”的中间值——比 29 大、比 37 小,实测在常见英文单词集(超 5 万词)上碰撞率极低,稳定优于邻近候选数(33、37、39、41)。
31 支持高效位运算优化
JVM 能把 31 * h 自动替换成 (h ,也就是左移 5 位再减自身。这个等价变换成立,因为 <code>2⁵ = 32,所以 31 × h = 32 × h − h = (h 。位移和减法比乘法指令快得多,尤其在早期 CPU 上优势明显;现代 JVM 仍保留这项优化,无需开发者手动改写,开箱即用。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
31 是奇数,避免信息丢失
如果用偶数(比如 32)作乘数,每次乘法都等价于左移加补零,低位有效位会逐步被“清空”。例如连续乘以 2 三次,相当于左移三位,原数值最低三位完全丢失。而 31 是奇数,每次乘法都会搅动所有比特位,有助于保留字符的原始差异,提升散列敏感度。
立即学习“Java免费学习笔记(深入)”;
它对应一种自然的“31 进制”编码逻辑
String 的哈希公式本质是:
s[0] × 31n−1 + s[1] × 31n−2 + … + s[n−1]
这类似于把字符串看作一个以 31 为底的整数:高位字符权重更大,低位字符影响更精细。这种设计让相似字符串(如 "abc" 和 "abd")大概率生成明显不同的哈希值,有利于区分。

















