为什么当我重写 equals() 方法时要重写 hashCode() ?

问题描述 投票:0回答:5

我从很多地方和来源听说,每当我重写

equals()
方法时,我也需要重写
hashCode()
方法。但请考虑下面的代码

package test;

public class MyCustomObject {
    
    int intVal1;
    int intVal2;
    
    public MyCustomObject(int val1, int val2){
        intVal1 = val1;
        intVal2 = val2;
    }
    
    public boolean equals(Object obj){
        return (((MyCustomObject)obj).intVal1 == this.intVal1) && 
                (((MyCustomObject)obj).intVal2 == this.intVal2);
    }
    
    public static void main(String a[]){
        MyCustomObject m1 = new MyCustomObject(3,5);
        MyCustomObject m2 = new MyCustomObject(3,5);
        MyCustomObject m3 = new MyCustomObject(4,5);
        
        System.out.println(m1.equals(m2));
        System.out.println(m1.equals(m3));
    }
}

这里的输出是 true, false 正是我想要的,我根本不关心覆盖

hashCode()
方法。这意味着
hashCode()
覆盖是一种选择,而不是像大家所说的那样是强制性的。

java equals hashcode
5个回答
36
投票

它适合您,因为您的代码不使用任何需要

hashCode()
API 的功能(HashMap、HashTable)。

但是,您不知道您的类(可能不是一次性编写的)稍后是否会在确实使用其对象作为哈希键的代码中被调用,在这种情况下,事情将会受到影响。

根据对象类的文档

hashCode 的通用约定是:

  • 在 Java 应用程序执行期间,只要在同一个对象上多次调用 hashCode 方法,只要对象上的 equals 比较中使用的信息没有被修改,hashCode 方法就必须始终返回相同的整数。从一个应用程序的一次执行到同一应用程序的另一次执行,该整数不需要保持一致。

  • 如果根据 equals(Object) 方法两个对象相等,则对这两个对象调用 hashCode 方法必须产生相同的整数结果


11
投票

因为HashMap/Hashtable会先通过hashCode()来查找对象。

如果它们不相同,hashmap将断言对象不相同并返回映射中不存在。


6
投票

您需要

@Override
两者都不需要或两者都不需要的原因是它们与 API 其余部分相互关联的方式。

您会发现,如果您将

m1
放入
HashSet<MyCustomObject>
中,则它不会
contains(m2)
。这是不一致的行为,可能会导致很多错误和混乱。

Java 库拥有大量功能。为了让它们为您工作,您需要遵守规则,并确保 equals

hashCode
保持一致是最重要的之一。
    


4
投票
a.equals(b)

==>

a.hashCode() == b.hashCode()
(注意逆矩阵不成立)。

但是作为附加信息,您可以做这个练习:

class Box { private String value; /* some boring setters and getters for value */ public int hashCode() { return value.hashCode(); } public boolean equals(Object obj) { if (obj != null && getClass().equals(obj.getClass()) { return ((Box) obj).value.equals(value); } else { return false; } } }

这样做:

Set<Box> s = new HashSet<Box>(); Box b = new Box(); b.setValue("hello"); s.add(b); s.contains(b); // TRUE b.setValue("other"); s.contains(b); // FALSE s.iterator().next() == b // TRUE!!! b is in s but contains(b) returns false

您从这个示例中学到的是,使用可以更改(可变)的属性来实现 
equals

hashCode
是一个非常糟糕的主意。
    


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.