hashCode()是如何用Java实现的

Adr*_*ian 6 java hash

hashCode()是如何实现的?

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

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

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

谢谢 :)

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

G. *_*cki 21

不不不.此主题中的所有答案都是错误的,或者至少只是部分正确.

第一种: Object.hashCode()是一种本机方法,因此它的实现完全取决于 JVM.它可能因HotSpot和其他VM实现(如JRockitIBM J9)而异.

如果你问:

如何hashCode()在Java中实现?

然后答案是:它取决于您使用的是哪个VM.

假设您正在使用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
Run Code Online (Sandbox Code Playgroud)

以上内容是从这篇文章中复制.

如果你在HotSpot源代码中挖掘一下,你可能会在下面的代码片段中找到:

if (hashCode == 0) {
  value = os::random();
} else {
  ...
Run Code Online (Sandbox Code Playgroud)

os::random() 只是Park-Miller伪随机生成器算法的实现.

就这样.没有任何内存地址的概念.虽然另外两个实现,  1并  4使用对象的内存地址,但默认的不使用它.基于对象地址
的概念Object.hashCode()在很大程度上是一个历史性的假象 - 它不再是真实的.


我知道在Object#hashCode()JavaDoc中我们可以读到:

(...)这通常通过将对象的内部地址转换为整数来实现,但Java™编程语言不需要此实现技术.

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


Tom*_*ine 5

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

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

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