IdentityHashMap通过==判断键身份、用System.identityHashCode()计算哈希值,实现仅依据内存地址区分对象,故new String("a")与new String("a")被视为不同key,而字面量"a"因共享地址被视作同一key。

IdentityHashMap 通过直接使用 == 运算符 比较键的内存地址,而不是调用 equals() 方法,从而实现“认对象身份、不认内容”的行为。
它怎么做到只看地址不看内容
核心在于两个机制协同工作:
-
键相等性判断用 ==:每次插入或查找时,IdentityHashMap 不调用
key1.equals(key2),而是直接写key1 == key2。只要不是同一个对象实例(即堆中同一块内存地址),就视为不同 key。 -
哈希值计算用 System.identityHashCode():它不依赖对象重写的
hashCode(),而是调用 JVM 提供的底层方法,该方法基于对象分配时的内存地址生成哈希码——哪怕你把hashCode()改成固定返回 1,identityHashCode 依然稳定反映对象唯一性。
为什么 new String("a") 和 new String("a") 在里面不冲突
因为它们是两个独立创建的字符串对象:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 虽然内容相同、
equals()返回 true,但 JVM 分配了两块不同内存; -
==判断结果为 false; -
System.identityHashCode()返回两个不同的整数; - 所以 IdentityHashMap 把它们当作完全无关的两个 key,各自存进 map。
注意字符串字面量是个例外
像 "hello" 这样的字面量会进入字符串常量池,多次出现实际指向同一对象:
立即学习“Java免费学习笔记(深入)”;
IdentityHashMap.put("a", 1);IdentityHashMap.put("a", 2);- 第二行会覆盖第一行——不是 bug,是因为两个
"a"是同一个对象,==为 true。
它的内部结构也配合这个逻辑
IdentityHashMap 不用 Node 链表或红黑树,而是用一个扁平的 Object[] table 数组:
-
table[0]存第一个 key,table[1]存对应 value; -
table[2]存第二个 key,table[3]存对应 value; - 查找时按哈希值定位起始索引,再用
==逐个比对 key 地址,线性探测直到匹配或遇到 null。

















