HashCode() 和 equals() 的关系
ps:作者是正在学习Java的小白,文章内容主要借鉴于JavaGuide,并且根据自己需要进行了一些改动,便于以后coding使用,原文地址:https://github.com/Uplpw/JavaGuide/blob/master/docs/java/basis/Java基础知识.mdhashCode 和 equals的关系hashCode是什么?equal()是什么?hashCode() 和
ps:作者是正在学习Java的小白,文章内容主要借鉴于JavaGuide,并且根据自己需要进行了一些改动,便于以后coding使用,原文地址:https://github.com/Uplpw/JavaGuide/blob/master/docs/java/basis/Java基础知识.md
hashCode 和 equals的关系
hashCode是什么?
hashCode()
的作用是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。
hashCode()
定义在 JDK 的 Object
类中,这就意味着 Java 中的任何类都包含有 hashCode()
函数。
equal()是什么?
equals()
作用不能用于判断基本数据类型的变量,只能用来判断两个对象是否相等。equals()
方法存在于Object
类中,而Object
类是所有类的直接或间接父类。
equals()
方法存在两种使用情况:
- 类没有覆盖
equals()
方法 :通过equals()
比较该类的两个对象时,等价于通过“==”比较这两个对象,使用的默认是Object
类equals()
方法。 - 类覆盖了
equals()
方法 :一般我们都覆盖equals()
方法来比较两个对象中的属性是否相等;若它们的属性相等,则返回 true(即,认为这两个对象相等)。
hashCode() 和 equals()的关系
一般来说,hashCode()
和 equals()
的关系分2种情况。
第一种情况
本质不是是散列表的数据结构(散列表是指如HashSet, Hashtable, HashMap的数据结构),此时hashCode()
和 equals()
就没有关系。
这种情况下,为了比较两个对象是否相等,只需要重写equals()
。
参考代码如下:
class Animal {
private String type;
private int age;
public Animal(String type, int age) {
this.type = type;
this.age = age;
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (this.getClass() != obj.getClass()) {
return false;
}
Animal animal = (Animal) obj;
return this.type.equals(animal.type) && this.age == animal.age;
}
public String toString() {
return "(" + this.type + ", " + this.age + ")";
}
}
public class HashCodeAndEqual {
public static void main(String[] args) {
Animal animal1 = new Animal("dog", 1);
Animal animal2 = new Animal("dog", 1);
Animal animal3 = new Animal("cat", 1);
System.out.println("animal1.equals(animal2): " + animal1.equals(animal2));
System.out.println("animal1.hashCode(): " + animal1.hashCode() + ", animal2.hashCode(): " + animal2.hashCode());
System.out.println("animal1.equals(animal3): " + animal1.equals(animal3));
System.out.println("animal1.hashCode(): " + animal1.hashCode() + ", animal3.hashCode(): " + animal3.hashCode());
}
}
结果如下:
animal1.equals(animal2): true
animal1.hashCode(): 713338599, animal2.hashCode(): 168423058
animal1.equals(animal3): false
animal1.hashCode(): 713338599, animal3.hashCode(): 821270929
结果分析:
equals()相等情况下,hashCode()不一定相等,所以本质不是是散列表的数据结构,此时hashCode()
和 equals()
是没有关系的。
第二种情况
本质是是散列表的数据结构,此时hashCode()
和 equals()
是有关系的。
这种情况下,为了比较两个对象是否相等,不仅要重写equals()
还要重写hashCode()
。
参考代码如下:
class Plant {
private final String type;
private final int age;
public Plant(String type, int age) {
this.type = type;
this.age = age;
}
// @Override
// public int hashCode(){
// int typeHash = this.type.toLowerCase().hashCode();
// return typeHash * age;
// }
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (this.getClass() != obj.getClass()) {
return false;
}
Plant animal = (Plant) obj;
return this.type.equals(animal.type) && this.age == animal.age;
}
public String toString() {
return "(" + this.type + ", " + this.age + ")";
}
}
public class HashCodeAndEqual {
public static void main(String[] args) {
Plant plant1 = new Plant("tree", 10);
Plant plant2 = new Plant("tree", 10);
Plant plant3 = new Plant("flower", 1);
Plant plant4 = new Plant("Tree", 10);
HashSet<Plant> plantSet = new HashSet<>();
plantSet.add(plant1);
plantSet.add(plant2);
plantSet.add(plant3);
plantSet.add(plant4);
System.out.println("plant1.equals(plant2): " + plant1.equals(plant2));
System.out.println("plant1.hashCode(): " + plant1.hashCode() + ", plant2.hashCode(): " + plant2.hashCode());
System.out.println("plant1.equals(plant3): " + plant1.equals(plant3));
System.out.println("plant1.hashCode(): " + plant1.hashCode() + ", plant3.hashCode(): " + plant3.hashCode());
System.out.println("plant1.equals(plant4): " + plant1.equals(plant4));
System.out.println("plant1.hashCode(): " + plant1.hashCode() + ", plant4.hashCode(): " + plant4.hashCode());
System.out.println(plantSet);
}
}
结果如下:
// 注释掉重写的hashCode()
plant1.equals(plant2): true
plant1.hashCode(): 1160460865, plant2.hashCode(): 1247233941
plant1.equals(plant3): false
plant1.hashCode(): 1160460865, plant3.hashCode(): 258952499
plant1.equals(plant4): false
plant1.hashCode(): 1160460865, plant4.hashCode(): 603742814
[(tree, 10), (Tree, 10), (tree, 10), (flower, 1)]
// 加上重写的hashCode()
plant1.equals(plant2): true
plant1.hashCode(): 35685420, plant2.hashCode(): 35685420
plant1.equals(plant3): false
plant1.hashCode(): 35685420, plant3.hashCode(): -1271629221
plant1.equals(plant4): false
plant1.hashCode(): 35685420, plant4.hashCode(): 35685420
[(tree, 10), (Tree, 10), (flower, 1)]
结果分析:
(1)注释掉重写的hashCode()
重写了equals()
。但是,HashSet中仍然有重复元素,why?这是因为虽然plant1 和 plant2的内容相等,但是它们的hashCode()
不等;所以,HashSet在添加plant1 和 plant2的时候,认为它们不相等。
(2)加上重写的hashCode()
此时重写的equals()
生效了,HashSet中没有重复元素。同时也发现,即使是hashCode()
相等而equals()
不相等。
总结
综上,使用散列表判断两个对象是否相等时,优先使用hashCode()
来判断,如果不等,则直接判断两个对象不等,如果相等再使用equals()
判断两个对象是否相等。
最后建议,重写equals()
时最好重写hashCode()
,这样不管是什么本质的数据结构都不会出现问题。
参考
https://www.cnblogs.com/skywang12345/p/3324958.html
更多推荐
所有评论(0)