2012-04-11 51 views
4

hashCode()如何实现?hashCode()如何在Java中实现

我的假设是,它使用该对象的存储位置为在其上运行散列函数的初始数量(种子)。然而,这种情况并非如此。

我也看了Hash : How does it work internally?,但它并没有回答我的问题。

是的,我可以下载SDK,但我做到这一点,之前看代码,也许别人已经拥有的知识它。

谢谢:)

编辑: 我知道它应该被覆盖和这样的,所以请尽量留在题目:)

+1

来自您自己的链接:*“这通常通过将对象的内部地址转换为整数来实现,但Java™编程语言不需要此实现技术。”*当然,这是在实施的自由裁量权,但这应该证实你对Oracle实施的假设。你为什么说不是这样? – 2012-04-11 13:25:51

+0

它具有自己的本地实现,如果你看到对象类 - public native int hashCode(); – 2012-04-11 13:45:36

+0

@MarkPeters以及当对象在内存中移动时会发生什么? – Adrian 2012-04-11 13:59:11

回答

3

当然是实施方式特定的,但是通常为一个对象的哈希码将被懒惰地计算并存储在对象头。奇怪的事情与标题完成,以保持他们的小,同时允许复杂的锁定算法。

在OpenJDK的/ Oracle的JVM计算初始散列码的通常的方法是基于在所述第一请求的时间的存储器地址。对象在内存中移动,所以每次使用地址都不是一个好的选择。哈希码不是实际的地址 - 通常是8的倍数,这对于在哈希表中直接使用而言并不是很好,特别是在具有两种尺寸的情况下。注意标识哈希码不是唯一的。

HotSpot有构建时间选项以始终使用零或使用安全随机数生成器(SRNG)进行测试。

+0

8的倍数可能会乘以一个素数以给出更好的可排序数 – Adrian 2012-04-11 13:54:54

+0

@Adrian它仍然是8的倍数。真的它会转移。 – 2012-04-11 17:40:06

+2

你是对的,我不知道我在想什么 – Adrian 2012-04-12 13:24:39

-1

我假设你正在谈论的Object实施hashCode,因为该方法可以并且应该被覆盖。

它取决于实现。对于Sun JDK,它基于对象的内存地址。

+1

我认为这有点误导。对象在内存中移动但具有稳定的身份哈希码。 – 2012-04-11 13:32:03

+0

@ TomHawtin-tackline究竟为什么我问这个问题;它看起来像一颗好种子(乘以一个素数),但是在你意识到物体被移动到内存中之后...... IDK – Adrian 2012-04-11 13:56:52

+0

由于两个原因Downvote。首先:通常不需要重写'hashCode'。其次:Sun的默认JDK是伪随机数,而不是对象的内存地址。你可以看到我的[post](http://stackoverflow.com/a/26975908/1037316)找到一点。 – 2014-11-17 15:28:10

0

hashcode()函数的实现因对象而异。如果你想知道一个特定的类是如何实现hashcode()的,你必须为这个类查找它。

0

由类对象中定义的hashCode方法返回不同的对象不同的整数。这可以通过将对象的内部地址转换为整数来实现(但这种实现方式不是标准所要求的)。为了支持散列表(等于和hashCode),新类会覆盖hashCode,这很有趣: http://www.javapractices.com/topic/TopicAction.do?Id=28

14

不,不,不。此线程中的所有答案都是错误的,或者至少只是部分正确。

第一: Object.hashCode()是一个本地方法,因此其实施只取决于在JVM上。它可能在HotSpot和其他虚拟机实现(如JRockitIBM J9)之间变化。

如果你问:

如何在Java中实现hashCode()

那么答案是:这取决于你正在使用哪个虚拟机。

假设您使用Oracle的默认JVM —这是HotSpot,那么我可以告诉你HotSpot有六个实现。您可以通过命令行使用-XX:hashCode=n标志运行JVM选择它,在那里n可以是:

0 – Park-Miller RNG (default) 
1 – f(address, global_statement) 
2 – constant 1 
3 – Serial counter 
4 – Object address 
5 – Thread-local Xorshift 

以上摘自this post复制。

如果您在热点的源代码周围挖一点点,你可以在下面找到片段:

if (hashCode == 0) { 
    value = os::random(); 
} else { 
    ... 

os::random()只是公园 - 米勒伪随机数发生器算法的实现。

就是这样。 没有任何内存地址的概念。尽管有两个其他的实现,  1和  4,使用一个对象的内存地址,默认的一个不使用它。
Object.hashCode()基于对象地址的概念很大程度上是historic artefact - 它不再是真的。


我知道里面Object#hashCode() JavaDoc中我们可以看到:

(...)这一般是通过将该对象的内部地址转换成一个整数来实现的,但是这种实现技术不Java™编程语言所要求的。

但它已经过时和误导。