IdentityHashMap用==判断key是否相等,HashMap用equals();前者基于引用地址“身份相等”,后者基于hashCode()和equals()“逻辑相等”;哈希值分别来自System.identityHashCode()和key.hashCode();适用场景分别为对象实例区分与通用语义映射。

核心区别就一条:IdentityHashMap用 == 判断 key 是否相等,HashMap 用 equals()。
Key 相等的判定逻辑完全不同
HashMap 认为两个 key 相等,必须同时满足两个条件:hashCode() 返回值相同,且 equals() 返回 true。这体现的是“逻辑相等”。
IdentityHashMap 只看引用是否指向同一块内存地址,即 key1 == key2 成立才算相等,不调用 equals(),也不依赖重写的 hashCode() —— 这体现的是“身份相等”。
哈希值的来源不同
- HashMap 调用 key 对象自身的 hashCode() 方法计算桶位置,因此受类中 hashCode() 实现影响(比如 String、Integer 都重写了它)
- IdentityHashMap 使用 System.identityHashCode(),该值由 JVM 基于对象初始内存地址生成,无法被重写覆盖,始终反映对象唯一身份
实际行为差异一目了然
例如:
String a = new String("key");
String b = new String("key");
- 在 HashMap 中:a.equals(b) 为 true,且 hashCode() 相同 → put(b, ...) 会覆盖 a 对应的值,size 保持为 1
- 在 IdentityHashMap 中:a != b(不同实例)→ 两个键都被保留,size 变为 2
适用场景有明确分界
HashMap 是通用选择,适用于绝大多数业务场景,比如按用户 ID、订单号、配置名等“内容语义”做映射。
IdentityHashMap 用于需要严格区分对象实例的底层场景,例如:
- 对象图遍历时避免循环引用(如序列化/反序列化框架)
- 代理类或字节码增强中维护原始对象与代理对象的映射
- 缓存内部状态时,以对象引用本身为标识,而非其字段值










