java string的hashcode()基于字符内容计算并缓存,公式为s[0]×31^(n−1)+…+s[n−1],实际通过迭代h=31×h+c实现;选用31因其为奇质数可降低冲突,且支持位运算优化(31×i等价于(i

Java 中 String 的 hashCode() 是基于字符内容计算的,且结果会被缓存(lazy cache),避免重复计算。
哈希值的计算公式
对字符串 s,其哈希值按以下方式计算(与 Arrays.hashCode(char[]) 逻辑一致):
- 初始值为
h = 0 - 从左到右遍历每个字符
c:h = 31 * h + c - 等价于:
s[0] × 31^(n−1) + s[1] × 31^(n−2) + ... + s[n−1]
例如 "abc" 的计算过程:
((('a' × 31) + 'b') × 31) + 'c' → (97×31 + 98)×31 + 99 = 96354
哈希值如何被缓存
String 类内部有一个私有字段 hash(int 类型),初始值为 0:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 首次调用
hashCode()时,若hash == 0且字符串非空,则执行上述计算,并将结果赋给hash - 后续调用直接返回已缓存的
hash值 - 注意:
hash == 0并不意味着未计算过 —— 空字符串或某些特殊字符串(如"\0")本身哈希就是 0,所以 Java 还依赖一个额外隐式约定:只有当hash == 0且字符串长度 > 0 时,才视为未缓存
为什么选 31 作为乘数
31 是一个奇质数,具备良好散列分布特性,且 JVM 能将其优化为位移减法:31 * i == (i ,提升计算效率。
不可变性是缓存安全的前提
String 是不可变类,一旦创建,其字符序列和长度就不会改变。因此缓存的哈希值永远有效,无需失效机制或同步控制 —— 这也是 hash 字段无需 volatile 或加锁的原因。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










