java 当我覆盖 equals() 方法时,为什么要覆盖 hashCode()?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2707541/
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
Why should I override hashCode() when I override equals() method?
提问by bragboy
Ok, I have heard from many places and sources that whenever I override the equals() method, I need to override the hashCode() method as well. But consider the following piece of code
好的,我从很多地方和消息来源听说,每当我覆盖 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));
}
}
Here the output is true, false exactly the way I want it to be and I dont care of overriding the hashCode() method at all. This means that hashCode() overriding is an option rather being a mandatory one as everyone says.
这里的输出是真,假正是我想要的样子,我根本不在乎覆盖 hashCode() 方法。这意味着 hashCode() 覆盖是一种选择,而不是每个人都说的强制性选择。
I want a second confirmation.
我要第二次确认。
回答by DVK
It works for you because your code does not use any functionality (HashMap, HashTable) which needs the hashCode()API.
它对您有用,因为您的代码不使用任何需要hashCode()API 的功能(HashMap、HashTable)。
However, you don't know whether your class (presumably not written as a one-off) will be later called in a code that does indeed use its objects as hash key, in which case things will be affected.
但是,您不知道您的类(可能不是一次性编写的)以后是否会在确实使用其对象作为散列键的代码中调用,在这种情况下,事情会受到影响。
As per the documentation for Object class:
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
hashCode 的总合约为:
每当在 Java 应用程序执行期间在同一对象上多次调用它时,hashCode 方法必须始终返回相同的整数,前提是对象上的 equals 比较中使用的信息没有被修改。该整数不需要从应用程序的一次执行到同一应用程序的另一次执行保持一致。
如果根据 equals(Object) 方法两个对象相等,则对两个对象中的每一个调用 hashCode 方法必须产生相同的整数结果。
回答by Dennis C
Because HashMap/Hashtable will lookup object by hashCode() first.
因为 HashMap/Hashtable 将首先通过 hashCode() 查找对象。
If they are not the same, hashmap will assert object are not the same and return not exists in the map.
如果它们不相同,hashmap 将断言对象不相同并返回不存在于映射中。
回答by polygenelubricants
The reason why you need to @Overrideneither or both, is because of the way they interrelate with the rest of the API.
您不需要@Override或两者都需要的原因是它们与 API 的其余部分相互关联的方式。
You'll find that if you put m1into a HashSet<MyCustomObject>, then it doesn't contains(m2). This is inconsistent behaviorand can cause a lot of bugs and chaos.
你会发现,如果你放入m1a HashSet<MyCustomObject>,那么它就没有contains(m2)。这是不一致的行为,会导致很多错误和混乱。
The Java library has tons of functionalities. In order to make them work foryou, you need to play by the rules, and making sure that equalsand hashCodeare consistent is one of the most important ones.
Java 库具有大量功能。为了使他们的工作对你,你需要遵守游戏规则,并确保equals和hashCode一致是最重要的一个。
回答by Diego
Most of the other comments already gave you the answer: you need to do it because there are collections (ie: HashSet, HashMap) that uses hashCode as an optimization to "index" object instances, an those optimizations expects that if: a.equals(b)==> a.hashCode() == b.hashCode()(NOTE that the inverse doesn't hold).
大多数其他评论已经给了你答案:你需要这样做,因为有集合(即:HashSet、HashMap)使用 hashCode 作为优化来“索引”对象实例,这些优化期望如果:a.equals(b)==> a.hashCode() == b.hashCode()(请注意,逆不成立)。
But as an additional information you can do this exercise:
但是作为附加信息,您可以进行以下练习:
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; }
}
}
The do this:
这样做:
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
What you learn from this example is that implementing equalsor hashCodewith properties that can be changed (mutable) is a really bad idea.
你从这个例子中学到的是,实现equals或hashCode使用可以改变(可变)的属性是一个非常糟糕的主意。
回答by Almar
It is primarily important when searching for an object using its hashCode() value in a collection (i.e. HashMap, HashSet, etc.). Each object returns a different hashCode() value therefore you must override this method to consistently generate a hashCode value based on the state of the object to help the Collections algorithm locate values on the hash table.
在使用集合(即 HashMap、HashSet 等)中的 hashCode() 值搜索对象时,这一点非常重要。每个对象返回不同的 hashCode() 值,因此您必须重写此方法以根据对象的状态一致地生成 hashCode 值,以帮助集合算法在哈希表上定位值。

