很多人问复写equals一定要复写hashCode方法吗?
我们在判断对象是否相等的时候往往会用的equals方法,根据对象的某个值是否相同来决定对象是否相等,所以这里我们需要复写equals方法。例如下面的代码:
public class Persion {
private Integer id;
private Integer age;
private String name;
@Override
public boolean equals(Object obj) {
if(this.getClass()==obj.getClass()){
return id.equals(((Persion)obj).id);
}
return false;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static void main(String[] args) {
Persion p1 = new Persion();
p1.setId(1);
p1.setAge(1);
p1.setName("张三");
Persion p2 = new Persion();
p2.setId(1);
p2.setAge(2);
p2.setName("李四");
System.out.println(p1.equals(p2));
}
//返回的是true
那么问题来了,既然equals可以实现功能我们为什么还要复写hascCode,接着往下看:
@Test
public void testHashCode(){
HashMap<Persion, String> map1 = new HashMap<>();
Persion p1 = new Persion();
p1.setId(1);
p1.setAge(1);
p1.setName("张三");
map1.put(p1, "测试");
Persion p2 = new Persion();
p2.setId(1);
p2.setAge(2);
p2.setName("李四");
System.out.println(map1.containsKey(p2));
}
//返回的是false
因为hashMap(或是hashSet)的containsKey方法涉及到了hashCode的操作,
public boolean containsKey(Object paramObject)
{
return getNode(hash(paramObject), paramObject) != null;
}
static final int hash(Object paramObject)
{
int i;
return paramObject == null ? 0 : (i = paramObject.hashCode()) ^ i >>> 16;
}
这里如果想返回true,必须equals与hashCode同时返回true才行。
我们复写Persion的hashCode方法
@Override
public int hashCode() {
return id.hashCode();
}
再执行测试用例就可以返回true.
总结:理论上没有涉及到hashCode的操作,我们复写equals方法就可以,但是,java规范约定,如果重写equals方法,那也要重写hashCode方法,使equals为真的情况,hashCode的值也是相同的,所以我们在复写的equals的时候尽量也复写hashCode,保险一点。
补充:String与Integer的hashCode是根据他们包内的值来计算生成的,如果两个值相等则hashCode相等。
String a = "张三";
String b = "张三";
System.out.println(a.hashCode()==b.hashCode());
Integer c =1;
Integer d =1;
System.out.println(c.hashCode()==d.hashCode());