假设有一个User对象,包括主键(id)、姓名(name),年龄(age)三个属性。现在我们new出两个User对象,来比较他们是否相等。
这里我们只需要姓名和年龄相等,就认为User对象相等。
public class User {
private String id;
private String name;
private String age;
...
}
User user1 = new User("1", "xiaohua", "14");
User user2 = new User("2", "xiaohua", "14");
System.out.println((user1.equals(user2)));//打印为false
为什么结果为false呢?查看源码可知,比较的是两个对象的地址,相当于user1==user2,所以肯定不相等。
public boolean equals(Object obj) {
return (this == obj);
}
接下来我们重写equals方法,直接上代码。
@Override
public boolean equals(Object obj) {
/**
* 1.判断地址是否相等,如果地址相等说明是同一对象
* 如果地址不相等,再执行下面的操作
*/
if (this == obj) {
return true;
}
/**
* 2.判断非空性
* 对于任意非空引用x,x.equals(null)应该返回false
*/
if (obj == null) {
return false;
}
/**
* 3.比较对象中的字段
* 字段相等,则这两个对象相等
*/
if (obj instanceof User) {
User other = (User) obj;
if (equalsStr(this.name, other.name)
&& equalsStr(this.age, other.age)) {
return true;
}
}
return false;
}
首先我们先看下默认的hashCode方法
@Override
public int hashCode() {
return super.hashCode();
}
接下来我们再举一个案例,将new出的两个User对象放入HashCode中,再进行比较
@Test
public void testHashCodeObj(){
User user1 = new User("1", "xiaohua", "14");
User user2 = new User("2", "xiaohua", "14");
Set userSet = new HashSet<>();
userSet.add(user1);
userSet.add(user2);
System.out.println(user1.equals(user2));//结果:true
System.out.println(user1.hashCode() == user2.hashCode());//结果:false
}
为什么结果是false呢?通过看hashSet的add方法能够得知,add方法里面使用了对象的hashCode方法来判断,所以我们需要重写hashCode方法来达到我们想要的效果。接下来我们重写HashCode方法。
@Override
public int hashCode() {
int result = 17;
result = 31 * result + (name == null ? 0 : name.hashCode());
result = 31 * result + (age == null ? 0 : age.hashCode());
return result;
}
所以hashCode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都会根据存储对象的 hashCode值来进行判断是否相同的。