Joshua Bloch谈到Effective 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()
方法为这些对象生成相同的值?
答案 0 :(得分:2)
正如M. le Rutte和AxelH已经说过的那样,equals应该只对相同的对象返回true(应该可以随时切换并在代码中呈现相同的结果,无论使用哪个)。
解决此问题的一种方法是使用包装类,在Remove duplicates from a list of objects based on property in Java 8的答案中描述。 你创建它所以包装类只存储计算的模糊值并比较和使用equals和hashcode中的值,然后你可以使用unwrapp来获得实际值。
另一种方法是像yshavit那样做并做另一个类似String的方法:equalsIgnoreCase
答案 1 :(得分:1)
我建议您使用其他方法名称,例如fuzzyEquals
而不是equals
。您应该根据其使用情况查看hashCode
和equals
。许多Java类(如HashMap
)在未经您同意的情况下调用这两种方法,并要求他们严格遵守他们的想法。他们的想法不是你想要的,而是他们需要的。它是这样的:
通过重命名,你(a)让HashMap和他的朋友们高兴,(b)避免混淆,(c)提高可读性,(d)有两种不同的方法用于两种不同的事情,你可以单独使用或进一步结合使用。
答案 2 :(得分:1)
要完成,您应该查看数据模型。这是目前失败的那个人
Match
介于两个Team
之间。Team
有一个name
Team
有alias
(0..n)。你会有一些想法:
public Team{
private final String name;
private List<String> alias;
public Team(Sting name){ ... }
public boolean equals(Object obj){
// check name
}
public int hashCode(){
// hash the name
}
}
然后,只需查看Match
以相同的方式使用此类。
班级Team
可以提供检查与String
匹配的任何别名的方法,如果alias
中没有匹配/找到,则会使用name
进行检查你的算法。如果此alias
匹配,则将其添加到List
进行未来研究。
这样,您不需要每次都运行模糊算法。如果您希望用户使Team
匹配他选择的任何输入,那么它可能很有用。
答案 3 :(得分:0)
重要的是,match1 == match2
然后是match1.hashCode() == match2.hashCode()
。假设您有一个数据库,您可以使用id(数字)存储匹配项,然后您可以hashCode
返回ID并完成。
不使用数据库来跟踪您可以完成的匹配ID
为每个团队分配一个固定长度的数字ID,并将{id} hashCode
的结果连接起来。
例如,"Manchester City"
团队可以是团队1
和"Atlético Madryt"
团队2
。如果哈希值为32位,那么前16位可以是团队1
,最后16位是团队2
,如此代表所示。
// 16 bit for team 1 + 16 bit for team 2
0000000000000001 0000000000000010
这是一个有效的32位整数,它将匹配match1 == match2
然后match1.hashCode() == match2.hashCode()