java 如果 hashCode() 未被覆盖,对象的哈希码是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2237720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 20:14:17  来源:igfitidea点击:

What is an object's hash code if hashCode() is not overridden?

javaobjecthashcode

提问by java_geek

If the hashCode() method is not overridden, what will be the result of invoking hashCode() on any object in Java?

如果没有覆盖 hashCode() 方法,那么在 Java 中对任何对象调用 hashCode() 会产生什么结果?

采纳答案by Hans W

Typically, hashCode() just returns the object's address in memory if you don't override it.

通常,如果您不覆盖它,hashCode() 只会返回对象在内存中的地址。

From 1:

1

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

就合理实用而言,类 Object 定义的 hashCode 方法确实为不同的对象返回不同的整数。(这通常是通过将对象的内部地址转换为整数来实现的,但是 JavaTM 编程语言不需要这种实现技术。)

回答by Tagir Valeev

In HotSpot JVM by default on the first invocation of non-overloaded Object.hashCodeor System.identityHashCodea random number is generated and stored in the object header. The consequent calls to Object.hashCodeor System.identityHashCodejust extract this value from the header. By default it has nothing in common with object content or object location, just random number. This behavior is controlled by -XX:hashCode=nHotSpot JVM option which has the following possible values:

在JVM的HotSpot上默认的第一次调用非过负荷Object.hashCodeSystem.identityHashCode生成并存储在对象头中的随机数。随后调用Object.hashCodeSystem.identityHashCode仅从标头中提取此值。默认情况下,它与对象内容或对象位置没有任何共同之处,只是随机数。此行为由-XX:hashCode=nHotSpot JVM 选项控制,该选项具有以下可能的值:

  • 0: use global random generator. This is default setting in Java 7. It has the disadvantage that concurrent calls from multiple threads may cause a race condition which will result in generating the same hashCode for different objects. Also in highly-concurrent environment delays are possible due to contention (using the same memory region from different CPU cores).
  • 5: use some thread-local xor-shift random generator which is free from the previous disadvantages. This is default setting in Java 8.
  • 1: use object pointer mixed with some random value which is changed on the "stop-the-world" events, so between stop-the-world events (like garbage collection) generated hashCodes are stable (for testing/debugging purposes)
  • 2: use always 1(for testing/debugging purposes)
  • 3: use autoincrementing numbers (for testing/debugging purposes, also global counter is used, thus contention and race conditions are possible)
  • 4: use object pointer trimmed to 32 bit if necessary (for testing/debugging purposes)
  • 0:使用全局随机生成器。这是 Java 7 中的默认设置。它的缺点是来自多个线程的并发调用可能会导致竞争条件,从而导致为不同的对象生成相同的 hashCode。同样在高并发环境中,由于争用(使用来自不同 CPU 内核的相同内存区域)可能会出现延迟。
  • 5:使用一些线程局部异或移位随机生成器,它没有以前的缺点。这是 Java 8 中的默认设置。
  • 1:使用混合了一些随机值的对象指针,该值在“stop-the-world”事件中改变,因此在stop-the-world事件(如垃圾收集)之间生成的hashCodes是稳定的(用于测试/调试目的)
  • 2:始终使用1(用于测试/调试目的)
  • 3:使用自动递增数字(出于测试/调试目的,还使用全局计数器,因此可能存在争用和竞争条件)
  • 4:如有必要,使用修剪为 32 位的对象指针(用于测试/调试目的)

Note that even if you set -XX:hashCode=4, the hashCode will not always point to the object address. Object may be moved later, but hashCode will stay the same. Also object addresses are poorly distributed (if your application uses not so much memory, most objects will be located close to each other), so you may end up having unbalanced hash tables if you use this option.

请注意,即使您设置了-XX:hashCode=4,hashCode 也不会始终指向对象地址。对象可能会在稍后移动,但 hashCode 将保持不变。此外,对象地址分布很差(如果您的应用程序使用的内存不多,大多数对象将彼此靠近),因此如果您使用此选项,最终可能会出现不平衡的哈希表。

回答by Asaph

The implementation of hashCode()may differ from class to class but the contract for hashCode()is very specific and stated clearly and explicitly in the Javadocs:

的实现hashCode()可能因类而异,但其约定hashCode()非常具体,并在Javadocs 中清楚明确地说明:

Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable.

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

返回对象的哈希码值。支持此方法是为了哈希表,例如由 java.util.Hashtable 提供的哈希表。

hashCode 的总合约为:

  • 每当在 Java 应用程序执行期间在同一对象上多次调用它时,hashCode 方法必须始终返回相同的整数,前提是对象上的 equals 比较中使用的信息没有被修改。该整数不需要从应用程序的一次执行到同一应用程序的另一次执行保持一致。
  • 如果根据 equals(Object) 方法两个对象相等,则对两个对象中的每一个调用 hashCode 方法必须产生相同的整数结果。
  • 如果根据 equals(java.lang.Object) 方法两个对象不相等,则不需要对两个对象中的每一个调用 hashCode 方法必须产生不同的整数结果。但是,程序员应该意识到为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

就合理实用而言,类 Object 定义的 hashCode 方法确实为不同的对象返回不同的整数。(这通常是通过将对象的内部地址转换为整数来实现的,但是 JavaTM 编程语言不需要这种实现技术。)

hashCode()is closely tied to equals()and if you override equals(), you should also override hashCode().

hashCode()密切相关equals(),如果您覆盖equals(),您还应该覆盖hashCode().

回答by pgras

If hashcode is not overriden you will call Object's hashcode, here is an excerpt from its javadoc:

如果未覆盖哈希码,您将调用 Object 的哈希码,以下是其 javadoc 的摘录:

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

就合理实用而言,类 Object 定义的 hashCode 方法确实为不同的对象返回不同的整数。(这通常是通过将对象的内部地址转换为整数来实现的,但是 JavaTM 编程语言不需要这种实现技术。)

回答by tonio

the default hashcode implementation gives the internal address of the object in the jvm, as a 32 bits integer. Thus, two different (in memory) objects will have different hashcodes.

默认的 hashcode 实现给出了 jvm 中对象的内部地址,作为一个 32 位整数。因此,两个不同的(在内存中)对象将具有不同的哈希码。

This is consistent with the default implementation of equals. If you want to override equals for your objects, you will have to adapt hashCode so that they are consistent.

这与 equals 的默认实现一致。如果要覆盖对象的 equals,则必须调整 hashCode 以使它们保持一致。

See http://www.ibm.com/developerworks/java/library/j-jtp05273.htmlfor a good overview.

请参阅http://www.ibm.com/developerworks/java/library/j-jtp05273.html以获得一个很好的概述。

回答by anish

You must override hashCode in every class that overrides equals.Failure to do so will result in a violation of the general contract for Object.hashCode, which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.

您必须在每个覆盖 equals 的类中覆盖 hashCode。不这样做将导致违反 Object.hashCode 的一般契约,这将阻止您的类在conjunction with all hash-based collections 中正常运行,including HashMap, HashSet, and Hashtable.

回答by Ustaman Sangat

Not really an answer but adding to my earlier comment

不是真正的答案,而是添加到我之前的评论中

internal address of the object cannot be guaranteed to remain unchanged in the JVM, whose garbage collector might move it around during heap compaction.

不能保证对象的内部地址在 JVM 中保持不变,JVM 的垃圾收集器可能会在堆压缩期间移动它。

I tried to do something like this:

我试图做这样的事情:

public static void main(String[] args) {
    final Object object = new Object();
    while (true) {
        int hash = object.hashCode();
        int x = 0;
        Runtime r = Runtime.getRuntime();
        List<Object> list = new LinkedList<Object>();
        while (r.freeMemory() / (double) r.totalMemory() > 0.3) {
            Object p = new Object();
            list.add(p);
            x += object.hashCode();//ensure optimizer or JIT won't remove this
        }
        System.out.println(x);
        list.clear();
        r.gc();
        if (object.hashCode() != hash) {
            System.out.println("Voila!");
            break;
        }
    }
}

But the hashcode indeed doesn't change... can someone tell me how Sun's JDK actually implements Obect.hashcode?

但是哈希码确实没有改变……有人能告诉我 Sun 的 JDK 是如何实现 Obect.hashcode 的吗?

回答by Larsen

returns 6 digit hex number. This is usually the memory location of the slot where the object is addressed. From an algorithmic per-se, I guess JDK does double hashing (native implementation) which is one of the best hashing functions for open addressing. This double hashing scheme highly reduces the possibility of collisions.

返回 6 位十六进制数。这通常是对象被寻址的插槽的内存位置。从算法本身来看,我猜 JDK 会进行双重散列(本机实现),这是用于开放寻址的最佳散列函数之一。这种双重散列方案大大降低了冲突的可能性。

The following post will give a supportive idea -

以下帖子将提供一个支持性的想法-

Java - HashMap confusion about collision handling and the get() method

Java - 关于碰撞处理和 get() 方法的 HashMap 混淆

回答by ndeuma

Two objects with different hash code must not be equal with regard to equals()

关于equals(),具有不同哈希码的两个对象不能相等

a.hashCode() != b.hashCode()must imply !a.equals(b)

a.hashCode() != b.hashCode()必须暗示 !a.equals(b)

However, two objects that are not equal with regard to equals() can have the same hash code. Storing these objects in a set or map will become less efficient if many objects have the same hash code.

但是,对于 equals() 不相等的两个对象可以具有相同的哈希码。如果许多对象具有相同的哈希码,将这些对象存储在集合或映射中的效率会降低。

回答by kgiannakakis

You should try to implement the hash code so that different objects will give different results. I don't think there is a standard way of doing this.

您应该尝试实现哈希码,以便不同的对象给出不同的结果。我认为没有标准的方法可以做到这一点。

Read this article for some information.

阅读这篇文章了解一些信息