哈希码唯一性

Ele*_*eco 13 java hashcode

两个Object实例是否可能具有相同的哈希码?

理论上,对象的哈希码是从其内存地址派生的,因此所有哈希码都应该是唯一的,但是如果在GC期间移动对象会怎样?

Tom*_*ine 12

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

使用内存地址只是获取稍微随机数的一种方法.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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

RFE澄清文档,因为这种方式过于频繁:CR 6321873


Ric*_*dOD 11

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

"尽管相当实用,但是由Object类定义的hashCode方法确实为不同的对象返回不同的整数.(这通常通过将对象的内部地址转换为整数来实现,但JavaTM不需要此实现技术编程语言.)"

  • 好吧,对于某些体系结构的开始,地址空间大于int,因此两个不同的值可以产生相同的值. (3认同)
  • 我读了javadoc,但我不确定是什么意思"合理实用". (2认同)

eri*_*son 7

想一想.有无数个潜在对象,只有40亿个哈希码.显然,无限的潜在对象共享每个哈希码.

Sun JVM要么将Object哈希代码基于对象的稳定句柄,要么缓存初始哈希代码.GC期间的压缩不会改变hashCode().如果确实如此,一切都会破裂.

  • 谢谢,我确实发现hashcode实现在runtime/sychronizer.cpp中.它碰巧在FastHashCode方法中. (2认同)

GWL*_*osa 5

可能吗?

是.

是否以合理的频率发生?

没有.

  • 正是这个。不要*指望*它们是独一无二的,但不要期望它们是相同的。 (2认同)