How to sort by unique data?

I have the following code:

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

I want to add all EnglishWord to, where exactly one EnglishWord object for each unique word . I want Set sort on occurrenceNumber . Code that I already sorted according to occurrenceNumber but didn't add EnglishWord with a unique occurrenceNumber to Set . As a code, here is what I mean:

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

After that, the size of mySet is 1.

+4
source share
4 answers

You must either define both equals and hashCode or none of them. In your code for two instances of x and y from EnglishWord x.equals(y) == true while x.hashCode() != y.hashCode() will happen. This is not legal if you expect your class to work with collection classes from java.util. See Object JavaDoc . To fix this, add something like this:

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

The equals method must have the signature "public boolean equals (Object other)" - your equals accepts an EnglishWord parameter, which causes your method to be ignored. Fix:

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

Generally, using the @Override annotation can help make your encoding more robust against this error, since a run-time error thus turns into a compile-time error.

Also, your Comparable interface Comparable should probably use generics.

+4
source

You probably want to compare by occurrence number, and if it is 0 , compare the word

 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; } 
+4
source

TreeSet internally supported by TreeMap . TreeMap.put(Object, Ojbect) will use the compareTo method on your EnglishWord to determine where the new item should go in the tree. If the result of compareTo is 0, the method assumes the elements are equal.

This is somewhat contrary to the JavaDoc for TreeSet.add

Adds the specified item to this set if it is not already present. More formally adds the given element e to this set if the set does not have an element e2 such that (e == null? E2 == null: e.equals (e2)). If this collection already contains an element, the call is left unchanged and returns false.

JavaDoc for Comparable says

Highly recommended, but not strictly required, to (x.compareTo (y) == 0) == (x.equals (y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. Recommended language: "Note: this class has a natural order that is incompatible with peers."

You need to take this advice and also compare words when events coincide.

+1
source

A collection can have only one index and one order. What you want is two lines: one that ensures that the words are unique, and one that sorts by the number of spaces.

To do this, you need to save two collections, one of which is the set specified by the word for uniqueness, and the second, which is sorted by event and word.

Note: the fields used in collections in this way cannot be changed or you will get the wrong behavior. I suggest you make the fields final.

0
source

All Articles