1

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

4

3 回答 3

12

最初,这个答案忽略了一个事实,即 aTreeSet基于compareTo(),而不是进行比较equals()。已进行编辑以解决此问题。

您需要为您的对象正确定义equals(),hashCode()和。(由于它是 a而不是 a ,因此实施并不那么重要 - 但这是一种很好的做法。)compareTo()PlayerTreeSetHashSethashCode()

Equals 和 hashCode 需要考虑所有的字段。Eclipse 可以为您自动生成一个看起来与此类似的内容(Source > Generate hashcode and equals)。

如果您已经有一个不使用所有字段的自然排序顺序TreeSet,那么您可以为您的. 但是,即使您真的只想按字段的子集进行排序,也没有什么能阻止您按所有字段进行排序(不感兴趣的字段只扮演部分有趣的部分是相同的)。这里要注意的重要一点是 aTreeSet不是通过方法确定相等性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
}
于 2012-05-02T02:29:18.260 回答
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;
   }
}
于 2014-09-24T11:08:52.800 回答
0

TreeSet 实例使用其 compareTo(或 compare)方法执行所有元素比较,因此从集合的角度来看,此方法认为相等的两个元素是相等的。一个集合的行为是明确定义的,即使它的顺序与equals不一致;它只是不遵守 Set 接口的一般约定。

来自 Java Platform Standard Edition 8 文档TreeSet部分。

于 2018-04-20T12:12:26.430 回答