如何按非唯一数据排序设置?

时间:2010-09-17 16:14:53

标签: java

我有以下代码:

public class EnglishWord implements Comparable<EnglishWord> {

    private String word;// unique
    private int occurenceNumber; //not unique


    public EnglishWord(String word, int occurenceNumber) {
        this.word = word;
        this.occurenceNumber= occurenceNumber;
    }

    public boolean equals(EnglishWord anotherWord) {
        return word.equals(anotherWord.getWord());
    }

    public int compareTo(EnglishWord anotherWord) {
        return occurenceNumber - anotherWord.getOccurenceNumber;
    }

我想将所有EnglishWord添加到Set,其中每个唯一EnglishWord只有一个word对象。我希望SetoccurrenceNumber排序。我已经按occurrenceNumber对单词进行了排序,但没有将EnglishWord添加到occurrenceNumber的唯一Set。作为代码,这就是我的意思:

Set<EnglishWord> mySet= new TreeSet<EnglishWord>();
mySet.add(new EnglishWord("hello",8));
mySet.add(new EnglishWord("hi",8));

在此之后,mySet的大小为1。

4 个答案:

答案 0 :(得分:4)

您可能希望按occurenceNumber进行比较,如果是0,则按字词进行比较

public int compareTo(EnglishWord anotherWord) {
    int val = occurenceNumber.compareTo(anotherWord.occurenceNumber);
    if (val == 0){ //ok, these have the same occurence, but are they the same word? 
        val = word.compareTo(other.word);
    }
    return val;
}

答案 1 :(得分:4)

您应该定义equals和hashCode,或者不定义它们。在您的代码中,对于EnglishWord的两个x和y实例,x.equals(y) == true同时x.hashCode() != y.hashCode()会发生。如果您希望您的类使用java.util中的集合类,那么这是不合法的。见the Object JavaDoc。要解决此问题,请添加以下内容:

@Override
public int hashCode() {
    return this.word.hashCode();
}

equals方法必须具有签名“public boolean equals(Object other)” - 您的equals采用EnglishWord参数,这会导致您的方法被忽略。修正:

@Override
public boolean equals(Object other) {
    if (other == null) return false;
    if (other.getClass() != this.getClass()) return false;
    final EnglishWord ow = (EnglishWord) other;
    return ow.word.equals(this.word);
}

通常,使用@Override注释可以帮助您更好地对抗这种错误,因为运行时错误会以这种方式转换为编译时错误。

此外,您对Comparable接口的实现应该可以使用泛型。

答案 2 :(得分:1)

TreeSetTreeMap内部支持。 TreeMap.put(Object, Ojbect)将使用compareTo上的EnglishWord方法来确定新元素在树中的位置。如果compareTo的结果为0,则该方法假设元素相等。

这与TreeSet.add

的JavaDoc有些矛盾
  

将指定的元素添加到此集合中   如果它还没有出现。更多   正式地,添加指定的元素e   如果集合包含否,则为此集合   元素e2这样(e == null?   e2 == null:e.equals(e2))。如果这个设定   已包含元素,调用   保持设置不变并返回   假的。

Comparable的JavaDoc说

  

强烈建议,但并非严格要求(x.compareTo(y)== 0)==(x.equals(y))。一般来说,任何实现Comparable接口并且违反此条件的类都应该清楚地表明这一事实。推荐的语言是“注意:此类具有与equals不一致的自然顺序。”

您需要接受此建议,并在事件发生时进行比较。

答案 3 :(得分:0)

一个集合只能有一个索引和一个排序。你想要的是两个凹凸,一个确保单词是唯一的,另一个是按出现次数排序。

要做到这一点,你需要维护两个集合,一个集合,一个单词用单词键入唯一性,第二个集合按出现和单词排序。

注意:以这种方式在集合中使用的字段无法更改,否则您将获得不正确的行为。我建议你让场地最后。