hashCode()如何实施?
我的假设是它使用对象内存位置作为运行哈希函数的初始数(种子)。但事实并非如此。
我也看过Hash : How does it work internally?,但它没有回答我的问题。
是的我可以下载SDK,但在我这样做并查看代码之前,也许其他人已经了解它。
谢谢:)
修改 我知道它应该被覆盖等等,所以请尽量保持主题:)
答案 0 :(得分:20)
不,不,不。此主题中的所有答案都是错误的,或者至少只是部分正确。
第一:
Object.hashCode()
是一种本机方法,因此它的实现仅仅依赖于在JVM上。它可能会在HotSpot与其他VM实施(例如JRockit或IBM J9)之间变化。
如果你问:
如何在Java中实现
hashCode()
?
然后答案是:这取决于您使用的是哪个VM。
假设您正在使用Oracle的默认JVM(即HotSpot),那么我可以告诉您HotSpot有六个hashCode()
实现。您可以使用运行JVM的-XX:hashCode=n
标志通过命令行选择它,其中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复制的。
如果您在HotSpot源代码中稍微挖掘一下,可以在下面找到代码段:
if (hashCode == 0) {
value = os::random();
} else {
...
os::random()
只是Park-Miller伪随机生成器算法的实现。
这就是全部。 没有任何内存地址的概念。虽然另外两个实现1
和4
使用对象的内存地址,但默认值不使用它。登记/>
Object.hashCode()
基于对象地址的概念主要是historic artefact - 它不再是真的。
我知道在Object#hashCode()
JavaDoc里面我们可以读到:
(...)这通常是通过将对象的内部地址转换为整数来实现的,但Java™编程语言不需要这种实现技术。
但它已经过时且具有误导性。
答案 1 :(得分:3)
当然它是特定于实现的,但通常对象的哈希码将被懒惰地计算并存储在对象头中。奇怪的事情是使用标题来保持它们小,同时允许复杂的锁定算法。
在OpenJDK / Oracle JVM中,计算初始哈希码的常用方法是基于第一次请求时的内存地址。对象在内存中移动,因此每次使用地址都不是一个好选择。哈希码不是实际地址 - 通常是8的倍数,这对于在哈希表中直接使用而言并不是很好,特别是具有两个大小的幂。注意身份哈希码不是唯一的。
HotSpot具有构建时间选项,可以始终使用零或使用安全随机数生成器(SRNG)进行测试。
答案 2 :(得分:0)
hashcode()函数的实现因Object而异。如果你想知道一个特定的类如何实现hashcode(),你将不得不查找该类。
答案 3 :(得分:0)
Object类定义的hashCode方法为不同的对象返回不同的整数。这可以通过将对象的内部地址转换为整数来实现(但标准不要求此实现样式)。新的类覆盖hashCode以支持哈希表(equal和hashCode),这很有趣: http://www.javapractices.com/topic/TopicAction.do?Id=28
答案 4 :(得分:-1)
我假设您正在讨论Object
hashCode
的实现,因为该方法可以而且应该被覆盖。
它依赖于实现。对于Sun JDK,它基于对象的内存地址。