为什么重写equals方法一定要重写hashcode方法
程序员文章站
2022-03-15 20:52:26
...
为什么重写equals方法一定要重写hashcode方法
- equals() 定义在JDK的Object.java中。通过判断两个对象的地址是否相等(即,是否是同一个对象)来区分它们是否相等
- hashCode()的作用是获取散列码
- 如果不使用HashTable,”hashCode() 和 equals() ”没有关系的!
HashSet、hashcoede()、equals()之间的关系
-
当用到散列表时,”hashCode() 和 equals() ”是有关系的!
例如:Hashset的插入的判断顺序是:先判断hashcode,不相同则插入;相同则继续比较equals是否为true,如果为true则表示两个对象相等,不能插入;如果是false则会散列到其他位置。
- 两个对象相等,equals为true
- 两个对象相等,hashcode一定相同(根据属性计算而来,相等的对象属性一定相等)
- equals为true、hashcode一定相同
- 相同的hashcode,对象不一定相等(equals不一定为true)
总结:
-
equals=true =》hashcode()相同 、反之不行
-
如果要使用散列表并且重写了equals方法就一定要重写hashcode()方法,以保证相同的对象不能同时加入HashSet中。
为什么重写equals方法一定要重写hashcode方法?
先看String
类重写的这两个方法
public boolean equals(Object anObject) {
//判断地址是否一样、一样则直接返回
if (this == anObject) {
return true;
}
//判断对象是否属于String类
if (anObject instanceof String) {
//开始比较
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
public int hashCode() {
//进行hash计算
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
现在来看自己写的类(要求 id和name 相同则视为同一个对象)
1、先看自动生成的者两个方法
默认生成的比较了book类的所有参数,以及进行了哈希运算。
class Book1 {
int id;
String name;
String author;
double price;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book1 book1 = (Book1) o;
return id == book1.id &&
Double.compare(book1.price, price) == 0 &&
Objects.equals(name, book1.name) &&
Objects.equals(author, book1.author);
}
@Override
public int hashCode() {
return Objects.hash(id, name, author, price);
}
}
2、要求是di和name相同则视为同一本书、即同一对象,相同的对象不能加入到散列表中,只需要比较id和name,改写如下
/**
* 重写equals方法比较id和name
* @param o
* @return
*/
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Book1 book1 = (Book1) o;
return id == book1.id && Objects.equals(name, book1.name);
}
/**
* 重写equals要重写hashcode set加入时会先判断hashcode是否相等,再判断是否equals
* 只有hashcode相同 和equals 同时成立 才能保证set的所有元素都不相等
* @return
*/
@Override
public int hashCode() {
return Objects.hash(id, name);
}
如果只是改写了equals方法 hashcode方法默认还是进行四个参数的哈希运算,计算出的两个对象的如果id和name相同,author或者price不同也会计算出不同的hashcode。这样的话我们自定义的两个相同的对象都能成功加入hashset,违背原则,所以必须同时覆盖这两个方法。
Book1 b1 = new Book1(1, "hh", "zs", 122.0);
Book1 b2 = new Book1(1, "hh", "zh", 112.0);
这两个对象只能加进去一个到HashSet中
上一篇: 微信朋友圈能一次性删除吗?
推荐阅读
-
浅谈java 重写equals方法的种种坑
-
Java连载57-equals重写、finalize方法、hashCode方法
-
【java基础】为什么重写toString()方法?
-
一文搞懂hashCode()和equals()方法的原理
-
荐 java父类-Object类-equals与==-方法的重载和重写-游离块-this关键字
-
java中重写equals()方法的时候为什么要重写hashCode()方法?
-
哈希表中为什么要重写hashCode与equals方法
-
Java中为什么要重写hashCode方法和equals方法?
-
Java中如何正确重写equals方法
-
为什么重写equals方法后必须重写hashCode方法?