2010-09-17 8 views
4

J'ai le code suivant:Comment faire pour trier Par données non uniques?

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; 
    } 

Je veux ajouter tous EnglishWord s dans un Set où pour chaque word unique, il y a exactement un objet EnglishWord. Je veux que le Set soit trié par occurrenceNumber. Le code que j'ai déjà trie les mots par occurrenceNumber, mais n'ajoute pas EnglishWord avec unique occurrenceNumber au Set. Code, voici ce que je veux dire:

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

Après cela, la taille de mySet est 1.

+0

ce n'est pas clair.please poster un exemple aussi. –

+0

J'ai peur qu'il soit difficile de comprendre votre question. Pourriez-vous essayer d'expliquer davantage, idéalement avec des exemples de données? (À la fois l'entrée et la sortie désirée)? –

+0

@Jon: J'ai réécrit la question à ma meilleure compréhension, bien que la partie * "with uniqueNumber to the Set" * était/est toujours confuse pour moi. – Esko

Répondre

4

Vous devez définir à la fois equals et hashCode ou aucun d'entre eux. Dans votre code, pour deux instances x et y de EnglishWord, il arrivera que x.equals(y) == true tandis que x.hashCode() != y.hashCode(). Ce n'est pas légal si vous attendez que votre classe travaille avec les classes de collection de java.util. Voir the Object JavaDoc. Pour corriger cela, ajoutez quelque chose comme ceci:

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

La méthode equals doit avoir la signature « public boolean equals (Object autre) » - vos égaux prend un paramètre EnglishWord qui se traduit par votre méthode étant essentiellement ignorée.Correction:

@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); 
} 

En général, en utilisant l'annotation @Override peut aider beaucoup à rendre votre codage plus robuste contre ce genre d'erreur que l'erreur d'exécution est transformée en une erreur de compilation de cette façon.

De plus, votre implémentation de l'interface Comparable devrait probablement utiliser des génériques.

4

Vous voulez probablement comparer par occurenceNumber, et si cela est 0, puis comparer par mot

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

TreeSet est soutenu en interne par un TreeMap. TreeMap.put(Object, Ojbect) utilisera la méthode compareTo sur votre EnglishWord pour déterminer où le nouvel élément doit aller dans l'arborescence. Si le résultat de compareTo est 0, la méthode suppose que les éléments sont égaux.

Ceci est quelque peu contredite par le JavaDoc pour TreeSet.add

Ajoute l'élément spécifié à cet ensemble si elle est pas déjà présent. Plus formellement, ajoute l'élément spécifié e à cet ensemble si l'ensemble ne contient pas élément e2 tel que (e == nul? e2 == null: e.equals (e2)). Si cet ensemble contient déjà l'élément, l'appel laisse l'ensemble inchangé et renvoie false.

Le JavaDoc pour Comparable dit

Il est fortement recommandé, mais pas strictement nécessaire que (x.compareTo (y) == 0) == (x.equals (y)). D'une manière générale, toute classe qui implémente l'interface Comparable et viole cette condition devrait clairement indiquer ce fait. La langue recommandée est "Note: cette classe a un ordre naturel qui est incompatible avec des égaux."

Vous devez suivre ce conseil et également comparer les mots lorsque les occurrences sont identiques.

0

Une collection peut avoir un seul index et un seul ordre. Ce que vous voulez, c'est deux indecies, une qui assure que les mots sont uniques et une seconde qui est triée par numéro d'occurance. Pour ce faire, vous devez gérer deux collections, une qui définit un ensemble, tapé par mot pour l'unicité et la seconde qui est triée par occurance et par mot.

Remarque: les champs utilisés dans les collections de cette manière ne peuvent pas être modifiés ou vous obtiendrez un comportement incorrect. Je vous suggère de rendre les champs définitifs.

Questions connexes