1.重写equals()和hashcode()
参考链接:https://blog.csdn.net/tracker_w/article/details/17068365
1) 重写equals()
因为在Object类中equals()比较的是两个的地址,由于使用new 产生的对象地址都是唯一的,所以如果不重写,那么A.equals(B)永远为false。
- 自反性:A.equals(A)要返回true.
- 对称性:如果A.equals(B)返回true, 则B.equals(A)也要返回true.
- 传递性:如果A.equals(B)为true, B.equals©为true, 则A.equals©也要为true. 说白了就是 A = B , B = C , 那么A = C.
- 一致性:只要A,B对象的状态没有改变,A.equals(B)必须始终返回true.
- A.equals(null) 要返回false.
// code 1.1
class Coder {
private String name;
private int age;
// getters and setters
public boolean equals(Object obj) {
if (obj == this) { // 先比较是否为自身
return true;
}
if ( !(obj instance of Coder) ) { // 再比较是否为其子类
return false;
}
Coder coder = (Coder) obj; // 经过上两次比较,此时可以转型,类型安全的
return coder.name.equals(this.name) && coder.age=this.age;
}
// 重写hashcode
@Override
public int hashCode(){
return name.hashCode() + age;
}
}
2)重写hashcode()
JDK8 的默认hashCode的计算方法是通过和当前线程有关的一个随机数+三个确定值。
实现方式为native,详细了解请参考https://juejin.im/entry/5968876df265da6c232898c2
在使用Map等散列结构的时候,需要使用hashcode值进行散列,如果不进行重写,根据object中原始的hashcode算法,两对象参数一样,hashcode也很难一样,那么同一个类产生的所有带有相同属性的对象都认为不相同,例如code 1.2
// code 1.2
class HashTest{
public void test(){
Set<Coder> hashset = new HashSet<>();
Coder coder1 = new Coder(); // name="chang", age=18;
Coder coder2 = new Coder(); // name="chang", age=18;
hashset.add(coder1);
boolean isContain = hashset.contains(coder2);
// 按照意图,isContain=true,但是为false;原因就是未重写hashcode,返回。
}
}
凭借自己之力很难写一个健壮的hashcode(),我们可以借助已经写好了的hashcode,例如在本例中我们可以使用code 1.3写法:
@Override
public int hashCode(){
return name.hashCode() + age;
}
String类中的hashcode写法无疑是健壮的,所以我们使用name的hashcode + age的方式。