Java String类的hashCode()返回基于字符串内容的确定性整数,计算公式为s[0]×31^(n−1)+…+s[n−1]×31^0(int运算,空串为0),实际通过h=31*h+char迭代实现,选用31因其为质数且支持位运算优化。

Java 中 String 类的 hash 值是通过一个确定性的多项式算法计算出来的整数,它不依赖内存地址,只取决于字符串内容本身。每次对同一字符串调用 hashCode(),结果必然相同;不同字符串则尽量产生不同结果,以减少哈希冲突。
核心公式:31 进制加权和
设字符串为 s,长度为 n,其中 s[0] 是首字符、s[n-1] 是末字符(按 ASCII 值参与运算),其 hash 值按如下方式计算:
s[0] × 31^(n−1) + s[1] × 31^(n−2) + … + s[n−2] × 31^1 + s[n−1] × 31^0- 所有运算使用
int类型的 32 位有符号整数算术(溢出自动截断) - 空字符串的 hash 值定义为
0
实际计算过程是迭代实现的
源码中并非真做幂运算,而是用循环逐步累积:
- 初始
h = 0 - 遍历每个字符:
h = 31 × h + 当前字符的 ASCII 值 - 例如
"Hi":
第一步:h = 31×0 + 'H' = 72
第二步:h = 31×72 + 'i' = 2232 + 105 = 2337
为什么选 31 作为乘数?
这个数字不是随意定的:
- 31 是质数,能有效降低因字符排列变化小而造成哈希值重复的概率
- 31 × h 可被 JVM 优化为
(h (左移 5 位再减自身),提升计算效率 - 实测在常见字符串分布下,31 比其他小质数(如 29、37)冲突率更低
hash 值会被缓存
String 对象不可变,所以首次调用 hashCode() 后,结果会存入内部字段 hash;后续调用直接返回缓存值,避免重复计算。

















