如果一个类有自己特有的“逻辑相等”,且需要以此进行比较时,那么就需要重写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; }
时间: 2024-10-25 17:24:13