如果覆盖equals方法却不覆盖hashCode方法,那么就很有可能出现两个对象equals方法返回true,但hashCode却不一致的情况,例如:在HashMap中取不到正确的value。
HashMap的get方法是用hashCode匹配的。
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
在重写equals方法的时候重写一下hashCode就可以了
public class People {
public People() {
}
private String name = "";
private String age;
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj instanceof People) {
People t = (People) obj;
if (this.name == t.name) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
int hash = 17;
hash = hash * 31 + name.hashCode(); //关键 用equals判断的属性的hashCode拼
return hash;
}
}
用lombok方式
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(exclude = {"age"})
public class People {
public People() {
}
private String name = "";
private String age;
}
lombok的@EqualsAndHashCode的说明,转自:https://blog.csdn.net/zhanlanmg/article/details/50392266
原文中提到的大致有以下几点:
1. 此注解会生成equals(Object other) 和 hashCode()方法。
2. 它默认使用非静态,非瞬态的属性
3. 可通过参数exclude排除一些属性
4. 可通过参数of指定仅使用哪些属性
5. 它默认仅使用该类中定义的属性且不调用父类的方法
6. 可通过callSuper=true解决上一点问题。让其生成的方法中调用父类的方法。
另:@Data相当于@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode这5个注解的合集。
通过官方文档,可以得知,当使用@Data注解时,则有了@EqualsAndHashCode注解,那么就会在此类中存在equals(Object other) 和 hashCode()方法,且不会使用父类的属性,这就导致了可能的问题。
比如,有多个类有相同的部分属性,把它们定义到父类中,恰好id(数据库主键)也在父类中,那么就会存在部分对象在比较时,它们并不相等,却因为lombok自动生成的equals(Object other) 和 hashCode()方法判定为相等,从而导致出错。
修复此问题的方法很简单:
1. 使用@Getter @Setter @ToString代替@Data并且自定义equals(Object other) 和 hashCode()方法,比如有些类只需要判断主键id是否相等即足矣。
2. 或者使用在使用@Data时同时加上@EqualsAndHashCode(callSuper=true)注解。