在写equals and hashCode 时,必须考虑哪些问题?
我不知道你是不是在刷问答?
你提的问题我综合给你描述下就是
两个对象equals相同,那么这两个对象的 hashCode一定相同
两个对象的 hashCode相同,不一定这两个对象相同。也就是equals比较不一定相同。
1、如果类需要是一个值类(value class),需要有以自己的逻辑相等场景(不等同于对象相同的概念),则需要覆盖equal方法。
2、覆盖equal时必须覆盖hashcode方法。保证自己逻辑下相等的对象散列值必须相同。
equals()必须定义一个等价关系(它必须是反射的、对称的和可传递的)。 此外,它必须是一致的(如果对象没有被修改,那么它必须继续返回相同的值)。 此外,o.equals (null)必须总是返回 false。
hashCode() 也必须是一致的(如果对象没有按照 equals ()进行修改,那么它必须继续返回相同的值)。
这两种方法的关系是:
每当 a.equals (b)时,a.hashCode ()必须与 b.hashCode ()相同。
实际操作:
如果你改写其中一个,那么也要改写另一个。
使用用于计算 equals ()以计算 hashCode ()的相同字段集。
使用 Apache Commons Lang 库中优秀的 helper 类 EqualsBuilder 和 HashCodeBuilder。 举个例子:
public class Person {
private String name;
private int age;
// ...
@Override
public int hashCode() {
return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
// if deriving: appendSuper(super.hashCode()).
append(name).
append(age).
toHashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Person))
return false;
if (obj == this)
return true;
Person rhs = (Person) obj;
return new EqualsBuilder().
// if deriving: appendSuper(super.equals(obj)).
append(name, rhs.name).
append(age, rhs.age).
isEquals();
}}
记住:
当使用基于散列的集合或映射(如 HashSet、 LinkedHashSet、 HashMap、 Hashtable 或 WeakHashMap)时,请确保放入集合中的键对象的 hashCode ()在对象位于集合中时不会发生更改。确保这一点的方法是让你的key不可变。
如果使用 Hibernate 等对象关系映射器(Object-Relationship Mapper,ORM)来处理类,那么有一些问题值得注意
延迟加载的对象是子类
如果您的对象使用 ORM ,在许多情况下您将处理动态代理,以避免过早从数据存储中加载对象。这些代理是作为自己类的子类实现的。 这意味着this.getClass() == o.getClass() 将返回 false。 例如:
Person saved = new Person("John Doe");Long key = dao.save(saved);
dao.flush();Person retrieved = dao.retrieve(key);
saved.getClass().equals(retrieved.getClass()); // Will return false if Person is loaded lazy
如果您正在处理 ORM,那么使用 o instanceof Person 是唯一正确的。
居然没有人提到guava library 么?这个很管用的
//Sample taken from a current working project of mine just to illustrate the idea
@Override
public int hashCode(){
return Objects.hashCode(this.getDate(), this.datePattern);
}
@Override
public boolean equals(Object obj){
if ( ! obj instanceof DateAndPattern ) {
return false;
}
return Objects.equal(((DateAndPattern)obj).getDate(), this.getDate())
&& Objects.equal(((DateAndPattern)obj).getDate(), this.getDatePattern());
}