20

Hashcode() 和 equals() 概念是

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

另一个是

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

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

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 ");
        }
    }
}

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

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

4

9 回答 9

30

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

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

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

于 2013-05-06T14:20:47.577 回答
8

字符串示例(以下所有字符串的哈希码均为 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());
    }
}

(从这篇文章中窃取)。

于 2013-05-06T14:22:17.513 回答
8

hashCode() 具有 32 位可能的值。你的对象可以有更多的东西,所以你将拥有一些具有相同 hashCode 的对象,即你不能确保它们是唯一的。

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

注意:在 HotSpot JVM 上,默认的 Object.hashCode() 永远不会是负数,即只有 31 位,尽管我不知道为什么。

如果您想生成许多具有相同 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();
}

这将生成 40 亿个 Long 且 hashCode 为 0。

于 2013-05-06T14:20:24.790 回答
5

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

于 2016-04-18T14:42:52.547 回答
1

其实很简单,

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

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

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

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

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

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

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

于 2013-05-06T14:29:15.147 回答
1

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

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

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

于 2019-07-07T14:07:14.973 回答
0

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

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

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

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

于 2013-12-06T18:06:22.570 回答
0

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

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

于 2016-07-22T18:48:36.193 回答
-1

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

我对 Java 很陌生,所以请谨慎回答。

于 2013-05-06T14:23:42.190 回答