Java HashMap或IdentityHashMap
在某些情况下,map中使用的键对象不会覆盖Object中的hashCode()和equals(),例如,使用套接字连接或java.lang.Class作为键Java HashMap或IdentityHashMap,java,Java,在某些情况下,map中使用的键对象不会覆盖Object中的hashCode()和equals(),例如,使用套接字连接或java.lang.Class作为键 将这些对象用作HashMap中的键是否存在任何潜在缺陷 在这些情况下我应该使用IdentityHashMap吗 据我所知,使用坏键的hashmap的唯一问题是使用非常大的hashmap—您的键可能非常坏,您得到的是o(n)检索时间,而不是o(1)。如果它确实破坏了其他任何东西,我很想听听:)如果在关键对象上没有覆盖equals()和hash
据我所知,使用坏键的hashmap的唯一问题是使用非常大的hashmap—您的键可能非常坏,您得到的是o(n)检索时间,而不是o(1)。如果它确实破坏了其他任何东西,我很想听听:)如果在关键对象上没有覆盖
equals()
和hashCode()
,HashMap和IdentityHashMap应该具有相同的语义。默认的equals()实现使用引用语义,默认的hashCode()
是对象的系统标识哈希代码
只有当一个对象的不同实例在逻辑上是相等的时,这才是有害的。例如,如果您的密钥是:
new Integer(1)
及
因为它们在技术上是Integer类的不同实例。(您确实应该使用Integer.valueOf(1)
,但这偏离了主题。)
Class
作为键应该是可以的,除非在非常特殊的情况下(例如,hibernate ORM库在运行时生成类的子类以实现代理)。作为开发人员,我对将Connection
对象存储在映射中作为键的代码持怀疑态度(如果您正在管理数据库连接,也许您应该使用连接池?)。它们是否有效取决于实现(因为连接只是一个接口)
另外,需要注意的是,HashMap期望
equals()
和hashCode()
的确定保持不变在key对象上使用可变字段,更改key字段可能会使key在HashMap的错误hashtable bucket中“丢失”。在这种情况下,您可以使用IdentityHashMap(取决于对象和特定用例),或者您可能只需要不同的equals()/hashCode()
实现。在您描述的情况下,HashMap和IdentityHashMap的行为是相同的
与此相反,如果键覆盖equals()和hashCode(),则两个映射的行为是不同的
请参见下面java.util.IdentityHashMap的javadoc
此类使用哈希表实现映射接口,在比较键(和值)时使用引用相等代替对象相等。换句话说,在IdentityHashMap中,两个键k1和k2被视为相等当且仅当(k1==k2)。(在正常映射实现中(如HashMap)两个键k1和k2被认为是相等的当且仅当(k1==null?k2==null:k1.equals(k2)))
总之,我的答案是:
虽然理论上没有问题,但除非您有明确的理由使用它,否则应该避免使用
IdentityHashMap
。在一般情况下,当您不可避免地开始向映射中引入覆盖equals()
和hashCode()的对象时,它不会提供明显的性能或其他好处
,您最终会发现一些微妙的、难以诊断的错误
如果出于性能原因,您认为需要
IdentityHashMap
,那么在切换之前,请使用探查器确认您的怀疑。我的猜测是,您将发现大量其他优化机会,这些机会既更安全,也会产生更大的影响。从移动代码安全的角度来看,在某些情况下,usingIdentityHashMap
或类似的方法是必要的。非final
关键类的恶意实现可以覆盖hashCode
和equals
为恶意类。例如,它们可以声明不同实例的相等性,获取对它们所比较的其他实例的引用,等等。我建议打破通过保持安全并在需要标识语义的地方使用IdentityHashMap
的标准做法。在已经比较超类的子类中,很少有很好的理由更改相等的含义。我猜最有可能的情况是一个损坏的非对称代理
IdentityHashMap
的实现与HashMap
大不相同。它使用线性探测而不是Entry
对象作为链中的链接。这导致对象的数量略有减少,尽管总内存使用量差异非常小。我没有任何可以提供的良好性能统计数据引用。使用(非重写)和Object.hashCode
和System.identityHashCode
,但这在几年前就被清除了。你的意思是糟糕的hashCode方法,不是吗?吹毛求疵-在一般情况下==
和System.identityHashCode
比典型的重载equals
和方法要快。但我同意t这通常不是使用IdentityHashMap
而不是HashMap
的好理由@Stephen C:很公平——我添加了一条免责声明。:)
new Integer(1)