String不可变使HashMap中哈希值缓存复用且桶位置长期稳定:内部private int hash字段首次计算后永久有效,避免重复遍历;哈希值不变确保键不“迷路”,提升查找效率并减少防御性拷贝。

Java 中 String 作为 HashMap 的键时,不可变性直接带来两项关键性能提升:哈希值缓存复用、桶位置长期稳定。
哈希值只需算一次,后续全走缓存
String 内部有一个 private int hash 字段,首次调用 hashCode() 时计算并写入,之后所有调用都直接返回这个值。因为内容不会变,哈希值就永远有效。
- 在 HashMap 的 get()、put()、containsKey() 等操作中,每次都要用 key 的 hashCode() 定位桶,缓存让这些调用变成 O(1) 时间的字段读取
- 对比可变类型(比如 StringBuilder),每次调用 hashCode() 都得遍历整个字符序列重新算,开销随长度线性增长
- 尤其在配置中心、路由表、HTTP 头名映射等大量字符串 key 场景下,缓存省下的 CPU 时间非常可观
键的位置不会漂移,查找不“迷路”
HashMap 把 key 的哈希值对数组长度取模,决定它存在哪个桶里。如果 key 可变,修改后哈希值变了,桶索引就变了——但旧值还留在原桶里,新哈希指向的桶里又没有它。
- 结果就是:key 明明还在 map 里,get() 却返回 null;或者 put 同一个 key 两次,map 里出现两个重复项
- String 不可变,意味着从放进 map 的那一刻起,它的哈希值和 equals 行为就锁死了,桶位置终身不变
- 不用额外做防御性拷贝或运行时校验,JVM 和 HashMap 实现都更轻量
配合字符串常量池,减少对象创建压力
字面量字符串(如 "user.id")会进常量池,多个地方用同一个 key,实际只有一份对象。
- 不可变性是池能安全复用的前提:否则一个地方改了 "user.id",所有用它作 key 的 map 都会错乱
- 减少了 GC 频率,也降低了 HashMap 内部 Entry 对象的引用复杂度
- 编译器还能对 "prefix" + "suffix" 这类纯字面量拼接做静态优化,进一步减少运行期对象生成
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











