若是一个类有本身特有的“逻辑相等”,且须要以此进行比较时,那么就须要重写equals方法。java
在Object的规范中,重写equals方法有下面几条通用约定:缓存
自反性。 x.equals(x) == trueide
对称性。if y.equals(x) == true , then x.equals(y) == true性能
传递性。if x.equals(y) == true y.equals(x) == true , then x.equals(z) == truecode
一致性。若是比较的对象没有被修改,那么屡次调用equals方法返回的结果应该相同
对象
有个示例对象以下:
hash
public class Book { private long id; private String name; private boolean isPublished; }
那么重写的equals方法示例以下:
class
@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; }