Java中的对象引用集合

17

我需要创建一个对象集合。重点是我不想基于对象的 hashCode 和 equals 实现来进行哈希或相等性比较。相反,我希望哈希码和相等性仅基于每个对象的引用标识(即引用指针的值)。

我不确定如何在Java中实现这一点。

这样做的原因是我的对象没有可靠地实现 equals 或 hashCode,而在这种情况下,引用标识已经足够了。

3个回答

29
我猜你需要的是java.util.IdentityHashMap(请注意,没有IdentityHashSet)。查阅API文档可以了解更多信息:
这个类使用哈希表实现了Map接口,当比较键(和值)时使用引用相等代替对象相等。换句话说,在IdentityHashMap中,仅当(k1==k2)时,两个键k1k2才被认为是相等的。(在正常的Map实现(如HashMap)中,仅当(k1==null ? k2==null : k1.equals(k2))时,两个键k1k2被认为是相等的。)
这个类不是一个通用的Map实现!虽然这个类实现了Map接口,但它有意违反了Map的一般约定,这个约定规定在比较对象时必须使用equals方法。这个类只适用于极少数需要引用相等语义的情况。 编辑:请参见Joachim Sauer下面的评论,很容易基于某个Map创建一个Set。你需要这样做:
Set<E> mySet = Collections.newSetFromMap(new IdentityHashMap<E, Boolean>());

4
实际上,一个 Set 只是一个忽略值的 Map。如果你不想一直在应用程序中处理它,你可以很容易地编写一个包装器,使其看起来更像一个“Set”。 - Jesper
2
+1 - 基于 Map 实现一个 Set 应该很容易。这就是 HashSet 的实现方式... - Stephen C
11
JDK中甚至有一种方法可以创建一个指定后台Map的Set,它被称为newSetFromMap:http://java.sun.com/javase/6/docs/api/java/util/Collections.html#newSetFromMap(java.util.Map%29 - Joachim Sauer
@Carl:你可以查看java.util.HashSet的源代码(可以在JDK安装目录下的src.zip文件中找到),你会发现它在内部使用了一个HashMap(正如Stephen C所说,它是基于HashMap实现的)。 - Jesper
@jesper:我改口了。特别是有Joachim Sauer的建议,这看起来像是一个赢家。 - Carl Smotricz
显示剩余3条评论

3
你可以将对象包装到一个包装类中,然后仅基于对象的身份实现hashcodeequals方法。

1
+1 - 这将是可行的,当他无法修复方法,并且扩展现有类不是一个选项时。 - Stephen C
1
如果你懒得编写自己的包装类,只需使用一个包含1个元素的Object[]。这样做很丑陋,但是可行。 - polygenelubricants
1
@polygenelubricants:聪明!我没有想到过。 - Carl Smotricz
@Carl:我自己从未使用过它(这是讨论的评论,而不是权威推荐的答案),但它继承了ObjectequalshashCode,并且已经有了getset,使它成为在这种情况下工作的包装器。我们实际上不需要它的原子性特性,但也不会有什么坏处。它可能仍然被视为滥用库类,但它不像使用new Object[1]数组那样丑陋。 - polygenelubricants
@polygenelubricants 使用只有一个元素的 Object[] 是行不通的:假设你想在普通的 Set 中使用它们,那么 new Object[] {obj}.equals(new Object[] {obj}) 的结果是 false - Marcono1234
显示剩余2条评论

1

你可以扩展HashSet(或者实际上是AbstractSet),并使用{{link1:IdentityHashMap}}作为其支持,该映射使用{{link2:System.identityHashCode(object)}}而不是obj.hashCode()

你可以简单地搜索IdentityHashSet,已经有一些实现了。或者像Joachim Sauer建议的那样使用Collections.newSetFromMap(..)

当然,只有在你没有“拥有”对象类的情况下才应该这样做。否则,只需修复它们的hashCode()即可。


似乎覆盖hashCode()比扩展HashSet更容易。 - danben
如果对象不在他的“拥有物”中 - Bozho
没错 - 听起来他们是这样,但我可能错了。 - danben
这些对象是Hibernate实体bean。由于以下原因,无法正确实现这些函数:1. 需要一个打开的Hibernate会话;2. 可能会遍历整个数据库! - Landon Kuhn
通常情况下,不需要使用Hibernate实体Bean时自带主键吗? - wds
在这种情况下,展示一下这些实体的使用 - 你可能使用了错误的字段来实现 hashCode() - Bozho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接