6

hashCode()是如何实现的?

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

我也看过Hash :它是如何在内部工作的?但它没有回答我的问题。

是的,我可以下载 SDK,但在我这样做并查看代码之前,也许其他人已经知道它了。

谢谢 :)

编辑: 我知道它应该被覆盖等等,所以请尽量保持话题:)

4

5 回答 5

23

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

首先: Object.hashCode()是一个native方法,所以它的实现完全依赖于JVM。HotSpot和其他 VM 实现(如JRockitIBM 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™ 编程语言不需要这种实现技术。

但它已经过时且具有误导性。

于 2014-11-17T15:21:26.673 回答
5

当然它是特定于实现的,但通常对象的哈希码将被延迟计算并存储在对象头中。奇怪的事情是用头来做的,以保持它们很小,同时允许复杂的锁定算法。

在 OpenJDK/Oracle JVM 中,计算初始哈希码的常用方法是基于第一次请求时的内存地址。对象在内存中移动,所以每次都使用地址不是一个好的选择。哈希码不是实际地址——它通常是八的倍数,不适合直接在哈希表中使用,尤其是具有两倍大小的幂。注意身份哈希码不是唯一的。

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

于 2012-04-11T13:38:55.497 回答
0

类 Object 定义的 hashCode 方法为不同的对象返回不同的整数。这可以通过将对象的内部地址转换为整数来实现(但标准不需要这种实现方式)。为了支持哈希表(equal 和 hashCode),覆盖 hashCode 的新类变得有趣: http ://www.javapractices.com/topic/TopicAction.do?Id=28

于 2012-04-11T13:43:13.090 回答
0

hashcode() 函数的实现因对象而异。如果您想知道特定类如何实现 hashcode(),则必须查找该类。

于 2012-04-11T13:39:57.657 回答
-1

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

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

于 2012-04-11T13:26:55.007 回答