若是一個類有本身特有的「邏輯相等」,且須要以此進行比較時,那麼就須要重寫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; }