hashCode()是如何实现的?
我的假设是它使用对象内存位置作为它运行散列函数的初始数字(种子)。然而,这种情况并非如此。
我也看过Hash :它是如何在内部工作的?但它没有回答我的问题。
是的,我可以下载 SDK,但在我这样做并查看代码之前,也许其他人已经知道它了。
谢谢 :)
编辑: 我知道它应该被覆盖等等,所以请尽量保持话题:)
hashCode()是如何实现的?
我的假设是它使用对象内存位置作为它运行散列函数的初始数字(种子)。然而,这种情况并非如此。
我也看过Hash :它是如何在内部工作的?但它没有回答我的问题。
是的,我可以下载 SDK,但在我这样做并查看代码之前,也许其他人已经知道它了。
谢谢 :)
编辑: 我知道它应该被覆盖等等,所以请尽量保持话题:)
不不不。此线程中的所有答案都是错误的,或者至少只是部分正确。
首先:
Object.hashCode()
是一个native方法,所以它的实现完全依赖于JVM。HotSpot和其他 VM 实现(如JRockit或IBM J9 )之间可能会有所不同。
如果您要问:
hashCode()
Java中是如何实现的?
那么答案是:这取决于您使用的是哪个虚拟机。
假设您使用的是 Oracle 的默认 JVM,即 HotSpot,那么我可以告诉您,HotSpot 有六个hashCode()
实现。您可以-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
以上是从这个帖子复制的。
如果您深入研究 HotSpot 源代码,您可能会发现以下代码段:
if (hashCode == 0) {
value = os::random();
} else {
...
os::random()
只是 Park-Miller Pseudo Random Generator 算法的实现。
就这样。没有任何内存地址的概念。尽管其他两个实现 1
和 4
使用对象的内存地址,但默认的不使用它。基于对象地址
的概念在很大程度上是一个历史文物——它不再是正确的。Object.hashCode()
我知道在Object#hashCode()
JavaDoc 中我们可以阅读:
(...) 这通常通过将对象的内部地址转换为整数来实现,但 Java™ 编程语言不需要这种实现技术。
但它已经过时且具有误导性。
当然它是特定于实现的,但通常对象的哈希码将被延迟计算并存储在对象头中。奇怪的事情是用头来做的,以保持它们很小,同时允许复杂的锁定算法。
在 OpenJDK/Oracle JVM 中,计算初始哈希码的常用方法是基于第一次请求时的内存地址。对象在内存中移动,所以每次都使用地址不是一个好的选择。哈希码不是实际地址——它通常是八的倍数,不适合直接在哈希表中使用,尤其是具有两倍大小的幂。注意身份哈希码不是唯一的。
HotSpot 具有构建时间选项以始终使用零或使用安全随机数生成器 (SRNG) 进行测试。
类 Object 定义的 hashCode 方法为不同的对象返回不同的整数。这可以通过将对象的内部地址转换为整数来实现(但标准不需要这种实现方式)。为了支持哈希表(equal 和 hashCode),覆盖 hashCode 的新类变得有趣: http ://www.javapractices.com/topic/TopicAction.do?Id=28
hashcode() 函数的实现因对象而异。如果您想知道特定类如何实现 hashcode(),则必须查找该类。
我假设您正在谈论 的Object
实现hashCode
,因为该方法可以而且应该被覆盖。
它依赖于实现。对于 Sun JDK,它基于对象的内存地址。