当我重写 equals() 方法时,为什么要重写 hashCode() ?
我从很多地方和来源听说,每当我重写 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()
覆盖是一种选项,而不是像大家所说的那样是强制性的。
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
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
它适合您,因为您的代码不使用任何需要
hashCode()
API 的功能(HashMap、HashTable)。但是,您不知道您的类(可能不是一次性编写的)稍后是否会在确实使用其对象作为哈希键的代码中被调用,在这种情况下,事情将会受到影响。
根据文档对象类:
It works for you because your code does not use any functionality (HashMap, HashTable) which needs the
hashCode()
API.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:
因为HashMap/Hashtable会先通过hashCode()来查找对象。
如果它们不相同,hashmap 将断言对象不相同并返回映射中不存在。
Because HashMap/Hashtable will lookup object by hashCode() first.
If they are not the same, hashmap will assert object are not the same and return not exists in the map.
您需要
@Override
两者都不需要,是因为它们与 API 其余部分相互关联的方式。您会发现,如果将
m1
放入HashSet
中,则它不会contains(m2)
。这是不一致的行为,可能会导致很多错误和混乱。Java 库具有大量功能。为了让它们为您工作,您需要遵守规则,并确保
equals
和hashCode
一致是其中之一最重要的。The reason why you need to
@Override
neither or both, is because of the way they interrelate with the rest of the API.You'll find that if you put
m1
into aHashSet<MyCustomObject>
, then it doesn'tcontains(m2)
. This is inconsistent behavior and can cause a lot of bugs and chaos.The Java library has tons of functionalities. In order to make them work for you, you need to play by the rules, and making sure that
equals
andhashCode
are consistent is one of the most important ones.大多数其他评论已经给了你答案:你需要这样做,因为有集合(即:HashSet、HashMap)使用 hashCode 作为“索引”对象实例的优化,这些优化期望如果: a.equals(b) ==>;
a.hashCode() == b.hashCode()
(注意,逆矩阵不成立)。但作为附加信息,您可以做这个练习:
这样做:
您从这个示例中学到的是使用可以更改(可变)的属性实现
equals
或hashCode
这是一个非常糟糕的主意。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).But as an additional information you can do this exercise:
The do this:
What you learn from this example is that implementing
equals
orhashCode
with properties that can be changed (mutable) is a really bad idea.当使用集合(即 HashMap、HashSet 等)中的 hashCode() 值搜索对象时,这一点尤为重要。每个对象都会返回不同的 hashCode() 值,因此您必须重写此方法,以根据对象的状态一致地生成 hashCode 值,以帮助 Collections 算法在哈希表上定位值。
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.