好的,我从许多地方和消息来源得知,每当我覆盖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));
}
}
这里的输出是真的,完全按照我想要的方式假,我根本不关心覆盖hashCode()方法。这意味着hashCode()覆盖是一个选项,而不是每个人都说的强制选项。
我想要第二次确认。
答案 0 :(得分:32)
它适用于您,因为您的代码不使用需要hashCode()
API 的任何功能(HashMap,HashTable)。
但是,您不知道您的类(可能不是一次性写入)稍后会在确实使用其对象作为哈希键的代码中调用,在这种情况下,事情会受到影响。
根据documentation for Object class:
hashCode的一般合约是:
每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是不修改对象上的equals比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,此整数不需要保持一致。
如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须生成相同的整数结果。
答案 1 :(得分:11)
因为HashMap / Hashtable将首先通过hashCode()查找对象。
如果它们不相同,则hashmap将断言对象不相同并且返回不存在于地图中。
答案 2 :(得分:5)
您之所以不需要@Override
的原因,是因为它们与API的其他部分相互关联。
您会发现,如果您将m1
放入HashSet<MyCustomObject>
,那么它就不会contains(m2)
。这是不一致的行为,可能会导致很多错误和混乱。
Java库具有大量功能。为了让它们为而工作,您需要遵守规则,并确保equals
和hashCode
一致是最重要的一个。< / p>
答案 3 :(得分:4)
大多数其他评论已经给出了答案:你需要这样做,因为有一些集合(即:HashSet,HashMap)使用hashCode作为“索引”对象实例的优化,这些优化期望如果: a.equals(b)
==&gt; 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
具有可以更改的属性(可变)是一个非常糟糕的主意。
答案 4 :(得分:0)
在使用集合中的hashCode()值(即HashMap,HashSet等)搜索对象时,这一点非常重要。每个对象都返回一个不同的hashCode()值,因此您必须覆盖此方法,以便根据对象的状态一致地生成hashCode值,以帮助Collections算法在哈希表上找到值。