【问题标题】:In Java object's hashcode is how to generate? [duplicate]Java中对象的hashcode是如何生成的? [重复]
【发布时间】:2015-09-08 05:55:04
【问题描述】:

在Java中,Object的hashcode值是根据对象的内容还是根据对象的实例内存地址通过算法生成的?

【问题讨论】:

  • @HarryBlargle,很遗憾,完全不正确的答案在那里得到了高度评​​价和接受。

标签: java object hashcode gethashcode


【解决方案1】:

如果你去Java源代码的Object类,它是这样实现的:

public native int hashCode();

本机hashCode 方法实现依赖于JVM。默认情况下,HotSpot 会根据对象的初始内存位置返回随机数,您可以在 source code(函数 get_next_hash)中查看。

根据Java docs这个方法

在合理可行的情况下,hashCode 方法定义为 类 Object 确实为不同的对象返回不同的整数。 (这 通常是通过转换的内部地址来实现 对象转换成整数,但这种实现技术不是 JavaTM 编程语言所要求的。)

但它总是依赖于 JVM 是如何实现 hashCode 方法的。

热点jvm中生成hashcode的Native方法实现:

static inline intptr_t get_next_hash(Thread * Self, oop obj) {
  intptr_t value = 0 ;
  if (hashCode == 0) {
     // This form uses an unguarded global Park-Miller RNG,
     // so it's possible for two threads to race and generate the same RNG.
     // On MP system we'll have lots of RW access to a global, so the
     // mechanism induces lots of coherency traffic.
     value = os::random() ;
  } else
  if (hashCode == 1) {
     // This variation has the property of being stable (idempotent)
     // between STW operations.  This can be useful in some of the 1-0
     // synchronization schemes.
     intptr_t addrBits = intptr_t(obj) >> 3 ;
     value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
  } else
  if (hashCode == 2) {
     value = 1 ;            // for sensitivity testing
  } else
  if (hashCode == 3) {
     value = ++GVars.hcSequence ;
  } else
  if (hashCode == 4) {
     value = intptr_t(obj) ;
  } else {
     // Marsaglia's xor-shift scheme with thread-specific state
     // This is probably the best overall implementation -- we'll
     // likely make this the default in future releases.
     unsigned t = Self->_hashStateX ;
     t ^= (t << 11) ;
     Self->_hashStateX = Self->_hashStateY ;
     Self->_hashStateY = Self->_hashStateZ ;
     Self->_hashStateZ = Self->_hashStateW ;
     unsigned v = Self->_hashStateW ;
     v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
     Self->_hashStateW = v ;
     value = v ;
  }

【讨论】:

  • 你的意思是对象的哈希码是随机整数。
  • 很多人会声称 Object.hashCode 会返回对象表示在内存中的地址。在现代实现中,对象实际上在内存中移动。取而代之的是,对象头的一个区域用于存储该值,该值可能是在首次请求该值时从内存地址中延迟派生的。但是这个实现实际上是依赖于JVM的。所以它可能因每个JVM而异。
  • 我相信随机数仅从内存位置生成,并用于进一步定位它。我已使用适当的 Javadoc 参考更新了答案以获取更多信息。
【解决方案2】:

应该从对象的内容生成自定义哈希码,而不是存储对象的内存位置。

您可以以任何您喜欢的方式为您的对象生成哈希码。但是,有一些规则:

  • 使用.equals() 的任何两个彼此“相等”的对象必须产生相同的哈希码值。
  • 但是,不是equal 的两个对象可以生成相同的哈希码值。

【讨论】:

  • 根据你的回答,我可以判断对象的hashcode是否是由对象内容生成的
  • 如果您正在编写类,您可以根据需要生成哈希码。但要确保其他类与您的类一起正常工作,您需要遵守上述规则。
【解决方案3】:

hashCode() 方法的默认实现基于object's identity 返回一个integer,并且不是基于对象的values of instance(和类)变量。 无论其实例变量(数据字段)的值改变多少次,默认的 hashCode 实现计算的哈希码在对象的生命周期内都不会改变。

您可以找到更多详细信息:HEREHERE

【讨论】:

  • 在编写自己的类时,hashcode方法不应该基于对象的身份——它应该基于其中存储的内容。
  • 你能解释一下对象的身份是什么
  • @wanghao 标识为内存地址(参考)。
猜你喜欢
  • 1970-01-01
  • 2020-01-26
  • 1970-01-01
  • 2015-12-23
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 2014-10-17
  • 2023-03-16
相关资源
最近更新 更多