Java 具有相同哈希码的两个不相等的对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16400711/
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-08-16 06:42:03  来源:igfitidea点击:

two unequal objects with same hashcode

javahashmapequalshashcode

提问by Saha

Hashcode() and equals() concept is

Hashcode() 和 equals() 的概念是

1) If two Objects are equal according to equal(), then calling the hashcode method on each of those two objects should produce same hashcode.

1) 如果根据 equal() 两个对象相等,则对这两个对象中的每一个调用 hashcode 方法应该产生相同的 hashcode。

and other one is

另一个是

2) It is not required that if two objects are unequal according to the equal(), then calling the hashcode method on each of the two objects must produce distinct values.

2) 如果根据 equal() 两个对象不相等,则不需要对两个对象中的每一个调用 hashcode 方法必须产生不同的值。

I tried and understood first one and this is the code for first point.

我尝试并理解了第一个,这是第一点的代码。

public class Test {
    public static void main(String[] args) {

        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        map.put(1, 11);
        map.put(4, 11);
        System.out.println(map.hashCode());
        Map<Integer, Integer> map1 = new HashMap<Integer, Integer>();
        map1.put(1, 11);
        map1.put(4, 11);
        System.out.println(map1.hashCode());
        if (map.equals(map1)) {
            System.out.println("equal ");
        }
    }
}

the above program gives same hashcode for two different objects.

上面的程序为两个不同的对象提供了相同的哈希码。

Can someone explain me with an example,how can two different objects which are unequal according to the equals() have same hashcode.

有人可以用一个例子来解释我,根据 equals() 不相等的两个不同对象如何具有相同的哈希码。

采纳答案by Jonathan

2) It is not requiredthat if two objects are unequalaccording to the equal(), then calling the hashcode method on each of the two objects must produce distinct values.

2)如果根据 equal()两个对象不相等,则不需要对两个对象中的每一个调用 hashcode 方法必须产生不同的值。

Depending on the hashing function, 2 different objects can have the same hash code. However, 2 objects which are the same must produce the same result when hashed (unless someone implemented a hashing function with random numbers in which case it's useless)

根据散列函数的不同,2 个不同的对象可以具有相同的散列码。但是,两个相同的对象在散列时必须产生相同的结果(除非有人用随机数实现了散列函数,在这种情况下它是无用的)

For example, if I am hashing integers and my hashing function is simply (n % 10)then the number 17and the number 27will produce the same result. This does not mean that those numbers are the same.

例如,如果我正在对整数进行散列,而我的散列函数只是简单的,(n % 10)那么数字17和数字27将产生相同的结果。这并不意味着这些数字是相同的。

回答by Peter Lawrey

hashCode() has 32-bit possible values. Your objects can have much more than this so you are going to have some objects with the same hashCode, i.e. you cannot ensure they will be unique.

hashCode() 有 32 位的可能值。您的对象可以拥有的远不止这些,因此您将拥有一些具有相同 hashCode 的对象,即您无法确保它们是唯一的。

This is made worse in a hash collection of a limited size. The maximum capacity of HashMap is 1 << 30 or about one billion. This means that only 30 bits are really used and if your collection doesn't use 16+ GB and is only say one thousand buckets (or 1 << 10 technically) then really you have only 1000 possible buckets.

这在有限大小的散列集合中变得更糟。HashMap 的最大容量为 1 << 30 或约 10 亿。这意味着只有 30 位真正被使用,如果你的集合不使用 16+ GB 并且只是说一千个存储桶(或技术上 1 << 10)那么你实际上只有 1000 个可能的存储桶。

Note: on the HotSpot JVM, the default Object.hashCode() is never negative i.e. only 31-bit, though I am not sure why.

注意:在 HotSpot JVM 上,默认的 Object.hashCode() 从不为负,即只有 31 位,但我不确定为什么。

If you want to generate lots of objects with the same hashCode look at Long.

如果您想生成大量具有相同 hashCode 的对象,请查看 Long。

// from Long
public int hashCode() {
    return (int)(value ^ (value >>> 32));
}

for(long i = Integer.MIN_VALUE; i < Integer.MAX_VALUE;i++) {
    Long l = (i << 32) + i;
    System.out.print(l.hashCode()+" ");
    if (i % 100 == 0)
        System.out.println();
}

This will generate 4 billion Long all with a hashCode of 0.

这将生成 40 亿个 Long,所有的 hashCode 都为 0。

回答by assylias

Example with Strings (all the strings below have a hashcode of 0):

字符串示例(以下所有字符串的哈希码均为 0):

public static void main(String[] args) {
    List<String> list = Arrays.asList("pollinating sandboxes",
                                      "amusement & hemophilias",
                                      "schoolworks = perversive",
                                      "electrolysissweeteners.net",
                                      "constitutionalunstableness.net",
                                      "grinnerslaphappier.org",
                                      "BLEACHINGFEMININELY.NET",
                                      "WWW.BUMRACEGOERS.ORG",
                                      "WWW.RACCOONPRUDENTIALS.NET",
                                      "Microcomputers: the unredeemed lollipop...",
                                      "Incentively, my dear, I don't tessellate a derangement.",
                                      "A person who never yodelled an apology, never preened vocalizing transsexuals.");
    for (String s : list) {
        System.out.println(s.hashCode());
    }
}

(stolen from this post).

(从这篇文章中窃取)。

回答by petematt62

My understanding is that hashCode is a numeric representation of the memory address, but is not the actual address. It can be changed, without affecting the actual address. Thus, it should be possible to set all objects to the same hashCode, even if they are all entirely different things. Think of everybody on one block all suddenly having the same street address. They are truly different people, but now all share the same street address. Their house didn't move, a mischevious teen just labeled everybody as "100 N. Main".

我的理解是 hashCode 是内存地址的数字表示,但不是实际地址。它可以更改,而不会影响实际地址。因此,应该可以将所有对象设置为相同的 hashCode,即使它们都是完全不同的东西。想想一个街区的每个人都突然拥有相同的街道地址。他们是真正不同的人,但现在都共享同一个街道地址。他们的房子没有动,一个淘气的少年只是给每个人贴上“100 N. Main”的标签。

I am pretty new to Java, so take my reply with a bit of caution.

我对 Java 还很陌生,所以请谨慎对待我的回复。

回答by Chris Cudmore

It's pretty simple actually,

其实很简单,

First we have to know what a hash code is.

首先我们要知道什么是哈希码。

In java, a hash code is simple a 32 bit signed integer that is somehow derived from the data in question. The integer types are usually just (Int Data) Mod (some reasonable large prime number).

在 Java 中,哈希码是一个简单的 32 位有符号整数,它以某种方式从相关数据中派生而来。整数类型通常只是 (Int Data) Mod(一些合理的大素数)。

Let's do a simple hash on integers.
Define:

让我们对整数做一个简单的散列。
定义:

public int hash(int num){ return num % 19 ; } 

In this case, both 19 and 38 will return the hash value of 0.

在这种情况下,19 和 38 都将返回哈希值 0。

For string types, the hash is derived from the individual characters and each ones position in the string, divided by a reasonably large number. (Or, in the case of Java, ignoring overflow in a 32 bit sum).

对于字符串类型,散列是从单个字符和每个字符在字符串中的位置除以相当大的数字得出的。(或者,在 Java 的情况下,忽略 32 位总和中的溢出)。

Given that there are arbitrarily many strings possible, and there is a limited number of hashcodes (2^32) for a string, the pigeon-hole principle states that there are at least two different strings that result in the same hashcode.

鉴于可能有任意多个字符串,并且一个字符串的哈希码数量有限(2^32),鸽巢原理指出至少有两个不同的字符串产生相同的哈希码。

回答by supercat

The purpose of hashCodeis to enable the following axiom and corollary:

的目的hashCode是启用以下公理和推论:

  • If one happens to know the hash codes of two objects, and those hash codes don't match, one need not bother examining the objects any further to know that the objects won't match. Even if two arbitrarily-chosen non-matching objects would have a 10% chance of having matching hash codes, testing hash codes would let one eliminate 90% of the comparisons one would otherwise need. Not as big a win as eliminating 99.99%, but definitely worthwhile nonetheless.

  • Knowledge that none of the objects in a bunch have a particular hash code implies that none of the objects in that bunch will match an object with that hash code. If one partitioned a collection of objects into those whose hash code was an even number and those whose hash was odd, and one wanted to find whether one had a given item whose hash code happened to be even, there would be no need to examine anything in the collection of of odd-hash items. Likewise there would be no need to look for an odd-hash item in the even-hash collection. Even a two-value hash could thus speed up searches by almost half. If one divides a collection into smaller partitions, one can speed things up even further.

  • 如果碰巧知道两个对象的散列码,而这些散列码不匹配,则无需进一步检查对象即可知道对象不匹配。即使两个任意选择的不匹配对象有 10% 的机会具有匹配的哈希码,测试哈希码也可以消除 90% 否则需要的比较。没有消除 99.99% 的胜利那么大,但绝对值得。

  • 一组对象中没有一个具有特定哈希码的知识意味着该组中的任何对象都不会与具有该哈希码的对象匹配。如果将一组对象划分为散列码为偶数的对象和散列值为奇数的对象,并且想要找出一个给定项目的散列码碰巧为偶数,则无需检查任何内容在奇数哈希项的集合中。同样,无需在偶数哈希集合中查找奇数哈希项。因此,即使是二值哈希也可以将搜索速度提高近一半。如果将一个集合划分为更小的分区,则可以进一步加快速度。

Note that hashCode()will offer the most benefit if every different item returns a different hash, but it can offer substantial benefit even when many items have the same hash value. The difference between a 90% savings and a 99.99% savings is often much greater than the numbers would suggest, and thus one if one can reasonably easily improve things to 99%, 99.9%, or better one should do so, but he difference between having zero false matches and having a few false matches in a collection is pretty slight.

请注意,hashCode()如果每个不同的项目返回不同的散列,这将提供最大的好处,但即使许多项目具有相同的散列值,它也可以提供实质性的好处。节省 90% 和节省 99.99% 之间的差异通常比数字所暗示的要大得多,因此,如果可以合理轻松地将事情改善到 99%、99.9% 或更好,那么应该这样做,但他之间的区别零错误匹配和集合中有一些错误匹配是非常轻微的。

回答by Steven Rock

I't pretty simple to understand if you know how a HashMap is implemented and it's purpose. A Hashmap takes a large set of values, and splits them into much smaller sets(buckets) for much faster retrieval of elements. Basically you only need to search the one bucket instead of the full list for your element. The buckets are in an array where the index is the hash code. Each bucket contains a linked list of elements with the same hashcode, but are not equal(). I think in Java 8 they switched to using a treemap when the bucket sizes becomes large.

如果您知道 HashMap 是如何实现的及其目的,我就不太容易理解。Hashmap 采用大量值,并将它们拆分为更小的集合(存储桶),以便更快地检索元素。基本上,您只需要搜索一个存储桶而不是元素的完整列表。存储桶位于一个数组中,其中索引是哈希码。每个存储桶包含具有相同哈希码但不相等()的元素的链表。我认为在 Java 8 中,当存储桶大小变大时,他们转而使用树形图。

回答by madhu_karnati

Actullay, this link explain what happens if hashcode equals more clearly.

Actullay,这个链接更清楚地解释了如果哈希码等于会发生什么。

http://www.javamadesoeasy.com/2015/02/hashmap-custom-implementation.html

http://www.javamadesoeasy.com/2015/02/hashmap-custom-implementation.html

回答by Vladimir Yel

I believe it will help you understand...

我相信它会帮助你理解...

The hashcode of a Java Object is simply a number, it is 32-bit signed int, that allows an object to be managed by a hash-based data structure. We know that hash code is an unique id number allocated to an object by JVM. But actually speaking, Hash code is not an unique number for an object. If two objects are equals then these two objects should return same hash code. So we have to implement hashcode() method of a class in such way that if two objects are equals, ie compared by equal() method of that class, then those two objects must return same hash code. If you are overriding hashCode you need to override equals method also.

Java 对象的哈希码只是一个数字,它是 32 位有符号整数,它允许对象由基于哈希的数据结构管理。我们知道哈希码是JVM分配给一个对象的唯一id号。但实际上,Hash 码并不是一个对象的唯一编号。如果两个对象相等,那么这两个对象应该返回相同的哈希码。所以我们必须以这样的方式实现一个类的 hashcode() 方法,如果两个对象相等,即通过该类的 equal() 方法进行比较,那么这两个对象必须返回相同的哈希码。如果您要覆盖 hashCode,则还需要覆盖 equals 方法。

ref: https://www.java2novice.com/java_interview_questions/hashcode/

参考:https: //www.java2novice.com/java_interview_questions/hashcode/