如果一个类有自己特有的“逻辑相等”,且需要以此进行比较时,那么就需要重写equals方法。
在Object的规范中,重写equals方法有下面几条通用约定:
自反性。 x.equals(x) == true
对称性。if y.equals(x) == true , then x.equals(y) == true
传递性。if x.equals(y) == true y.equals(x) == true , then x.equals(z) == true
一致性。如果比较的对象没有被修改,那么多次调用equals方法返回的结果应该相同
有个示例对象如下:
public class Book {
private long id;
private String name;
private boolean isPublished;
}
那么重写的equals方法示例如下:
@Override
public boolean equals(Object obj) {
if( !(obj instanceof Book))
return false;
Book b = (Book) obj;
return b.id == id
&& b.isPublished == isPublished
&& (b.name == name || (b != null && b.equals(b.name)) );
}
在重写了equals方法的类中,如果不重写hashcode方法,则所有基于hash的集合就没法正常使用。
重写hashCode方法示例如下:
@Override
public int hashCode() {
int hashCode = 3;
hashCode = 31 * hashCode + (int)(id ^ (id>>>32));
hashCode = 31 * hashCode + (name == null?0:name.hashCode());
hashCode = 31 * hashCode + (isPublished?1:0);
return hashCode;
}
如果这个类是不可变的,并且hashCode比较耗性能,则可以考虑缓存hashCode的值。
示例如下:
//使用volatile保证可见性
private volatile int hashCodeCache;
@Override
public int hashCode() {
int hashCode = hashCodeCache;
if(hashCode == 0){
hashCode = 3;
hashCode = 31 * hashCode + (int)(id ^ (id>>>32));
hashCode = 31 * hashCode + (name == null?0:name.hashCode());
hashCode = 31 * hashCode + (isPublished?1:0);
hashCodeCache = hashCode;
}
return hashCode;
}
原文:http://my.oschina.net/u/1756290/blog/381095