删除TreeSet中的重复项

时间:2012-05-02 02:27:25

标签: java collections arraylist treeset

我一直在使用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对象。

3 个答案:

答案 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部分。