equals方法比较的是两个对象的哈希码,这么说对吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了equals方法比较的是两个对象的哈希码,这么说对吗?相关的知识,希望对你有一定的参考价值。

如题

没有绝对的对错,如果你重装equals方法,让他去比较两个对象的哈希码来决定两个对象是否相同的话,那这么说就是对的了。否则的话是不能这么说的。

equals在原则上要和hashcode保持一致,即equals为真 两个对象hashcode应相同。 你之所以产生这个想法我想估计就这这样造成的。两个方法结果的一致性让你误以为是equals比较的是hashcode。

而在程序中真正的hashcode是和内存地址有关的,所以你可以想象每个对象的hashcode是不可能相同的,两个不一样的对象不能同时在一个内存地址上,这个肯定确保了不同对象的hashcod不同。
但是在实际运行中我们判断对象是否相同不需要那么严格,两个字符串内容一样我们就认为是相等了,而不去看他是不是在同一个内存地址上,所以这个时候我们就要重新写这个equals来达到当内容相同就返回true了,而不去管内存地址是不是一样了。。但是在很多map这类容器中判断对象是否相等则是同时比较equals和hashcode,所以为了保证这些重载过equals方法的类还能在这种情况下正常使用就规定了重载equals就一定要重载hashcode。这个也是为什么要求equals和hashcode一致性的原因。
参考技术A 请查看我的参考资料里的API

Object equlas 比较的是两者的内存地址。 但String等类都对equlas和hashCode进行了重写了,比较的实际内容是否相同。

equlas和hashCode的关系大致上有这样一种约定:
1.x.equlas(y) 返回true 那么x和y的hashCode必须相同
2.x.equlas(y) 返回false 那么x和y的hashCode不必须不相同,即也可以相同。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。

基于以上约定,所以一般重写了equals都会重写hashcode以保证以上的约定成立。所以equals比较的不是哈希码,而是内存地址。

参考资料:http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/lang/Object.html#equals(java.lang.Object)

参考技术B equals比较的变量实际的值,双等号(==)比较的是内存地址~内存一样当然值也是一样的~!! 参考技术C 你看看Object的equals方法就知道了,如下:
public boolean equals(Object obj)
return (this == obj);

它比较的是当前对象与所传入对象的引用的地址,所以你的问题不言而明了,它的后继类一般都会重写这个方法:如String类:
public boolean equals(Object anObject)
if (this == anObject)
return true;

if (anObject instanceof String)
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count)
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0)
if (v1[i++] != v2[j++])
return false;

return true;


return false;
参考技术D 不对!如果不重写就是==

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

【中文标题】具有相同哈希码的两个不相等对象【英文标题】:two unequal objects with same hashcode 【发布时间】:2013-04-30 07:47:14 【问题描述】:

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() 不相等的两个不同对象如何具有相同的哈希码。

【问题讨论】:

将可能的哈希码数量与可能的Longs 或Strings 的数量进行比较。 en.wikipedia.org/wiki/Pigeonhole_principle Example of ==, equals and hashcode in java的可能重复 点(1)和(2)的来源是什么? 【参考方案1】:

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

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

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

【讨论】:

【参考方案2】:

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

(从this post窃取)。

【讨论】:

【参考方案3】:

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

这在有限大小的哈希集合中变得更糟。 HashMap 的最大容量为 1

注意:在 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。

【讨论】:

如果你想生成很多具有相同hashCode的对象,重写“public int hashChode()”返回相同的hashCode不是更简单。这不是最终的。【参考方案4】:

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

【讨论】:

【参考方案5】:

相信会帮助你理解……

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

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

【讨论】:

【参考方案6】:

其实很简单,

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

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

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

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

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

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

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

【讨论】:

【参考方案7】:

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

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

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

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

【讨论】:

【参考方案8】:

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

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

【讨论】:

【参考方案9】:

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

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

【讨论】:

这实际上是一个关于哈希码是什么的完全错误的想法。

以上是关于equals方法比较的是两个对象的哈希码,这么说对吗?的主要内容,如果未能解决你的问题,请参考以下文章

如果两个对象的哈希码相同则他们不一定相同,如果对象一致则哈希码一定相同

Object Equals && GetHashCode

java Object里的equals比较的是对象的哈希值还是物理内存? "==" 比较的又啥?

equal和hashcode==

hashCode()和equals()

Java 中 hashCode 和 equals 方法是什么?它们和 == 各有什么区别?