搜索
您的当前位置:首页正文

为什么重写了equals方法一般也要重写hashCode方法

来源:哗拓教育

现在假设我们有一个矩形类Rectangle 

public class Rectangle {
private int length;
private int width;

public Rectangle(int length, int width) {
this.length = length;
this.width = width;
}
}
先回顾下我们为什么要覆盖equals方法呢?现在我们有两个矩形类的对象实例rectangle1 和rectangle2。

Rectangle rectangle1 = new Rectangle(3, 4);
Rectangle rectangle2 = new Rectangle(4, 3);
我想知道两个矩形是否是相等的,如果使用==运算符的话,比较的是rectangle1的引用和rectangle2的引用分别指向的对象在堆中存储的位置。两个对象是先后new出来的,所以肯定是在堆中有两个不同的对象,得到的结果就必然是false。

System.out.println(rectangle1 == rectangle2);
输出结果:false
这并不是我们想要的,我们的目的并不是想知道这两个引用是否是指向同一个对象,而是想知道这两个矩形的长宽是否相同,简单来说我们想要的是通过逻辑判断来得知这两个矩形rectangle1和rectangle2是否相等。所以我们通过覆盖equals方法来实现。

@Override
public boolean equals(Object obj) {
Rectangle o = (Rectangle) obj;
if (length == o.length){
if (width == o.width){
return true;
}else return false;
} else if (width == o.length) {
if (length == o.width) {
return true;
}else return false;
}
return false;
}
这个equals方法中,我们制定的规则是两个矩形,有相同的长、宽,即认为两个矩形是相同的。

这时再通过equals方法来判断两个矩形是否相等

System.out.println(rectangle1.equals(rectangle2));
输出结果: true

到这里我们已经满足了我们判断两个矩形是否相同的需求了。

那我们为什么还要覆盖hashCode方法呢?

HashMap<Rectangle, String> map2 = new HashMap<>(16);
map2.put(rectangle1, "nice");
map2.put(rectangle2, "bad");
System.out.println("size:"+map2.size());
输出结果:size:2

想要让rectangle1和rectangle2做为同一个key,在散列时落在同一个桶中,我们就必须要来覆盖hashCode方法

@Override
public int hashCode() {
//以下的17、31都是任意指定大小的数字。
int result = 17;
//这里我简单指定面积相同的矩形,hashCode值就相同
result = 31 * result + length*width;
return result;
}
这时再试一次

HashMap<Rectangle, String> map2 = new HashMap<>(16);
map2.put(rectangle1, "nice");
map2.put(rectangle2, "nice");
System.out.println("size:"+map2.size());
输出结果:size:1

这下得到了我们想要的结果。

我们在覆盖了hashCode方法之后,要问问自己”我们认为逻辑相等的实例是否都具有相等的散列码”。通过编写单元测试来验证一下你的推断。

总结:需要做逻辑相等判断的类,覆盖equals方法,如果还需要在散列表(HashMap、HashSet)中作为key,需要覆盖hashcode方法。


转自
原文:https:///gkmmg/article/details/80296238

转载于:https://www.cnblogs.com/xp0813/p/11293996.html

因篇幅问题不能全部显示,请点此查看更多更全内容

Top