【发布时间】:2018-03-27 18:33:08
【问题描述】:
Joshua Bloch 谈到有效的 Java:
您必须在每个覆盖 equals() 的类中覆盖 hashCode()。 否则将导致违反总合同 对于 Object.hashCode(),这将阻止你的类运行 与所有基于哈希的集合正确结合,包括 HashMap、HashSet、Hashtable。
我重写的equals() 方法实现了用于比较Match 对象的模糊评分算法:
public class Match {
private String homeTeam;
private String awayTeam;
public Match(String homeTeam, String awayTeam) {
this.homeTeam = formatTeamName(homeTeam);
this.awayTeam = formatTeamName(awayTeam);
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Match that = (Match) o;
final int threshold = 6;
return (computeFuzzyScore(this.homeTeam, that.awayTeam) <= threshold || computeFuzzyScore(this.awayTeam, that.homeTeam) <= threshold) &&
computeFuzzyScore(this.homeTeam, that.homeTeam) > threshold && computeFuzzyScore(this.awayTeam, that.awayTeam) > threshold;
}
// formatTeamName(), computeFuzzyScore() have been left out for brevity.
}
这样这些对象就相等了:
Match match0 = new Match("Man.City", "Atl.Madryt");
Match match1 = new Match("Manchester City", "Atlético Madryt");
我应该如何覆盖hashCode() 方法来为这些对象生成相同的值?
【问题讨论】:
-
match0和match不一样,不是吗。所以他们最好不拥有相同的hashCode()。你的equals()也不应该返回true。 -
您应该在哈希码文档中发现哈希码对于等效实例应该是相同的,但可能是不同的。这意味着哈希码应该只使用
equals中使用的变量。 -
你确定这个
equals方法是传递的吗? -
您的 equals 实现不是可传递的,但它需要符合 Object.equals 的约定。也就是说,如果 A 等于 B,B 等于 C,那么 A 最等于 C。如果前两个几乎不匹配模糊等式,而 A-C 比较不匹配,会发生什么情况?这就是为什么你很难想出一个好的 hashCode;你的平等被打破了。你应该使 equals 严格,并想出另一种模糊比较的方法,有点像 String.equals vs equalsIgnoringCase。
-
是的。但说实话,你误用了
equals。添加新方法。