我一直在使用ArrayList为我的项目存储板球队员并订购它们。 我开始考虑使用TreeSet,因为它具有删除重复项的优点。 然而,我遇到的问题是,如果我创建以下两个玩家:
P p1 = new P("Jack","Daniel",33(age),180(height),78(weight),41(games played),2300
(runs scored),41(dismisses))
P p2 = new P("Jack","Daniel",37(age),185(height),79(weight),45(games played),2560
(runs scored),45(dismisses))
请注意,这两个玩家的名字和名字相同,但其他一切都不同。当我尝试将这两个播放器添加到TreeSet时,它认为它们是重复的,因为名称相似并删除了第二个。显然我不希望这种情况发生,我希望Set只有当他拥有的所有内容与其他玩家相同时才移除玩家,而不仅仅是名字和姓氏。
有没有办法实现这个目标?
我的TreeSet也是一个Player对象。
答案 0 :(得分:11)
最初,这个答案忽略了TreeSet
根据compareTo()
而不是equals()
进行比较的事实。已编辑以解决此问题。
您需要正确定义equals()
对象的hashCode()
,compareTo()
和Player
。 (由于它是TreeSet
而不是HashSet
,因此实施hashCode()
并不是那么重要 - 但这是一种很好的做法。)
Equals和hashCode需要考虑所有字段。 Eclipse可以为您自动生成一个与此类似的内容( Source> Generate hashcode and equals )。
如果您已经有一个不使用所有字段的自然排序顺序,那么您可以为TreeSet
提供自定义比较器。然而,即使你真的只想按字段的子集排序,也没有什么能阻止你按所有字段排序(不感兴趣的字段只播放有趣部分的一部分是相同的)。这里要注意的重要一点是,TreeSet
不是通过equals()
方法确定平等,而是通过compareTo() == 0
确定平等。
这是一个例子equals():
@Override
public boolean equals(Object obj)
{
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Player that = (Player) obj;
return this.age == that.age &&
this.height == that.height &&
this.weight == that.weight &&
this.games == that.games &&
this.runs == that.runs &&
this.dismisses == that.dismisses &&
this.given.equals(that.given) &&
this.family.equals(that.family);
}
这是哈希码:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + this.age;
result = prime * result + this.dismisses;
result = prime * result + this.family.hashCode());
result = prime * result + this.games;
result = prime * result + this.given.hashCode());
result = prime * result + this.height;
result = prime * result + this.runs;
result = prime * result + this.weight;
return result;
}
最后,这是一个compareTo:
public int compareTo(Player that)
{
int result;
result = this.family.compareTo(that.family);
if (result != 0) // is the family name different?
{
return result; // yes ... use it to discriminate
}
result = this.given.compareTo(that.given);
if (result != 0) // is the given name different?
{
return result; // yes ... use it to discriminate
}
result = this.age - that.age; // is the age different?
if (result != 0)
{
return result; // yes ... use it to discriminate
}
... (and so on) ...
... with the final one ...
return this.dismisses - that.dismisses; // only thing left to discriminate by
}
答案 1 :(得分:0)
class Student implements Comparable<Student> {
String name;
public Student(String name) {
this.name=name;
}
public String toString(){
return name;
}
public int compareTo(Student gStudent) {
if(!this.name.equals(gStudent.getName()))
return 1;
return 0;
}
private String getName() {
return name;
}
}
答案 2 :(得分:0)
TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,这个方法认为相等的两个元素是相等的。集合的行为即使其排序与equals不一致也是明确定义的;它只是没有遵守Set接口的一般合同。
从Java平台标准版8文档TreeSet
部分。