14

是否有可能两个实例Object具有相同的hashCode()

理论上一个对象hashCode是从它的内存地址派生的,所以所有的都hashCodes应该是唯一的,但是如果在 GC 期间对象被移动了怎么办?

4

7 回答 7

14

我认为对象的 hashCode 方法的文档说明了答案。

“在合理可行的情况下,Object 类定义的 hashCode 方法确实为不同的对象返回不同的整数。(这通常通过将对象的内部地址转换为整数来实现,但 JavaTM 不需要这种实现技术编程语言。)”

于 2009-09-04T19:21:38.697 回答
13

给定一个合理的对象集合,很可能有两个具有相同的哈希码。在最好的情况下,它会变成生日问题,与数以万计的对象发生冲突。在实践中,对象是用相对较小的可能哈希码池创建的,并且只有数千个对象很容易发生冲突。

使用内存地址只是获得一个稍微随机数的一种方式。Sun JDK 源有一个开关,可以使用安全随机数生成器或常量。我相信 IBM(曾经?)使用快速随机数生成器,但它一点也不安全。文档中提到的内存地址似乎具有历史性质(大约十年前,具有固定位置的对象句柄并不罕见)。

这是我几年前编写的一些代码来演示冲突:

class HashClash {
    public static void main(String[] args) {
        final Object obj = new Object();
        final int target = obj.hashCode();
        Object clash;
        long ct = 0;
        do {
            clash = new Object();
            ++ct;
        } while (clash.hashCode() != target && ct<10L*1000*1000*1000L);
        if (clash.hashCode() == target) {
            System.out.println(ct+": "+obj+" - "+clash);
        } else {
            System.out.println("No clashes found");
        }
    }
}

RFE 澄清文档,因为这出现得太频繁了:CR 6321873

于 2009-09-04T20:02:11.097 回答
9

想想看。有无限多的潜在对象,只有 40 亿个哈希码。显然,无限的潜在对象共享每个哈希码。

Sun JVM 将Object散列码基于对象的稳定句柄或缓存初始散列码。GC 期间的压缩不会改变hashCode(). 如果这样做,一切都会崩溃。

于 2009-09-04T19:34:24.460 回答
6

是否可以?

是的。

它是否以任何合理的频率发生?

不。

于 2009-09-04T19:28:27.607 回答
1

我假设最初的问题只是关于默认Object实现生成的哈希码。事实上,哈希码不能被依赖于相等性测试,并且只用于一些特定的哈希映射操作(例如那些由非常有用的HashMap实现实现的操作)。

因此,它们不需要真正独特——它们只需要足够独特,不会产生很多冲突(这将使HashMap实现效率低下)。

此外,预计当开发人员实现要存储在 HashMaps 中的类时,他们将实现一个哈希码算法,该算法对于同一类的对象发生冲突的可能性很小(假设您只在应用程序 HashMaps 中存储同一类的对象),并且了解数据可以更容易地实现稳健的散列。

另请参阅 Ken 的关于需要相同哈希码的相等性的回答。

于 2009-09-04T22:59:27.637 回答
0

您是在谈论Object一般的实际类或对象吗?您在问题中同时使用两者。(而现实世界的应用程序通常不会创建很多实例Object

对于一般的对象,编写一个你想要覆盖的类是很常见的equals();如果你这样做,你还必须重写hashCode(),以便该类的两个“相等”的不同实例也必须具有相同的哈希码。在这种情况下,您可能会在同一类的实例中获得“重复”的哈希码。

此外,hashCode()在不同的类中实现时,它们通常基于对象中的某些内容,因此您最终会得到更少的“随机”值,从而导致不同类的实例之间的“重复”哈希码(无论这些对象是否“相等”) ”)。

在任何现实世界的应用程序中,找到具有相同哈希码的不同对象并不罕见。

于 2009-09-04T22:55:28.487 回答
-1

如果哈希码与内存地址一样多,那么将需要整个内存来存储哈希本身。:-)

所以,是的,哈希码有时应该会发生重合。

于 2009-09-04T20:22:50.540 回答