String的equals()与hashCode()严格遵循“相等对象必有相同哈希码”契约:equals逐字符比较内容并保证五大特性,hashCode用31幂次公式确定性计算且缓存结果,二者协同确保HashMap等集合高效可靠。

String 类的 equals 和 hashCode 是 Java 中最典型、最规范的重写范例,它们被设计为严格遵循 Java 规范中关于“相等对象必须有相同哈希码”的约定,并兼顾性能与语义准确性。
String.equals() 的重写逻辑
String 的 equals 方法不是简单比较引用,而是逐字符比对内容。它的核心逻辑包括:
- 先用
==快速判断是否为同一对象(自反性优化) - 检查参数是否为
null,避免空指针 - 用
getClass() != obj.getClass()确保类型一致(不接受子类或伪装对象) - 将参数强转为
String后,先比长度,再逐个char比较(利用value字节数组和coder编码标识支持 Latin-1 与 UTF-16 双模式)
这个实现保证了对称性、传递性、自反性和一致性——比如 "abc".equals("abc")、"abc".equals(null) 返回 false、"abc".equals(new String("abc")) 返回 true。
String.hashCode() 的计算方式
String 的 hashCode 使用确定性公式计算,结果仅依赖字符序列本身,与创建方式、内存地址完全无关。其算法是:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
s[0] × 31^(n−1) + s[1] × 31^(n−2) + ... + s[n−1]
其中 s[i] 是第 i 个字符的 Unicode 值,n 是字符串长度。Java 8+ 还做了缓存优化:hashCode 值首次计算后会存入私有字段 hash,后续调用直接返回,避免重复计算。
例如:"ab".hashCode() = 'a' * 31 + 'b' = 97 * 31 + 98 = 3105;"abc".hashCode() 可由该公式推得,且所有内容相同的字符串(无论用字面量还是 new String() 创建)必然得到相同哈希值。
为什么这两个方法能安全协同工作
String 同时满足关键契约:
- 若
s1.equals(s2) == true→ 必有s1.hashCode() == s2.hashCode()(因为公式只看字符,而 equals 也只看字符) - 若
s1.hashCode() != s2.hashCode()→ 可立即判定s1.equals(s2) == false(哈希不等,无需遍历) - 即使发生哈希碰撞(如
"Aa"和"BB"在某些旧版本中哈希相同),equals仍能最终正确区分
这使得 String 可以在 HashMap、HashSet 等集合中高效、可靠地作为键使用。

















