Delpux
Delpux

Reputation: 137

HashSet vs TreeSet different size()

I'm reading a file and adding the words to a HashSet and a TreeSet. HashSet.size() gives me 350 items but TreeSet.size() 349 items. Does anyone have an explanation of this difference?

public static void main(String[] args) throws FileNotFoundException {
    File file = new File("src/words.txt");
    Scanner read = new Scanner(file);
    Set<Word> hashSet = new HashSet<Word>();
    Set<Word> treeSet = new TreeSet<Word>();
    while(read.hasNext()) {
        Word word = new Word(read.next());
        hashSet.add(word);
        treeSet.add(word);
    }

    System.out.println(hashSet.size());
    System.out.println(treeSet.size());

    Iterator<Word> itr = treeSet.iterator();
    while (itr.hasNext()) {
        System.out.println(itr.next().toString());
    }
}

public class Word implements Comparable<Word> {

        private String word;

        public Word(String str) {
            this.word = str; }

        public String toString() {
            return word.toLowerCase(); }

        /* Override Object methods */
        public int hashCode() {
            int hashCode = 0;
            int temp;
            for(int i = 0; i<word.length();i++){
                temp = (int) word.charAt(i);
                hashCode += temp^hashCode;
            }
            return hashCode;
        }

        public boolean equals(Word other) {
            if(other instanceof Word){
            if(compareTo(((Word) other))==0)
                return true;
            else
                return false;}
            else
                return false;
        }


        public int compareTo(Word w) {
            if(this.word.compareToIgnoreCase(w.toString())>0)
                return 1;
            if(this.word.compareToIgnoreCase(w.toString())<0)
                return -1;
            else
                return 0;
        }


}

Upvotes: 1

Views: 289

Answers (2)

Rahul Agrawal
Rahul Agrawal

Reputation: 633

Your equals and compareTo method behaves differently for same input. E.g.

Word w1 = new Word("Word");
Word w2 = new Word("word");
System.out.println(w1 == w2);
System.out.println(w1.equals(w2));
System.out.println(w1.compareTo(w2));

will give

false
true
0

HashSet uses equals method to compare keys, while TreeSet will use compareTo method to check equivalence of keys. Since your implementation is not correct, for different scenarios, hashset will treat keys as different while treeset might be considering them as same.

To know which values are getting treated as same by TreeSet you can print the result of addition to the Sets. Both will return true, if key does not exist otherwise false is returned.

while(read.hasNext()) {
    Word word = new Word(read.next());
    System.out.println(hashSet.add(word));
    System.out.println(treeSet.add(word));
}

Upvotes: 1

ciamej
ciamej

Reputation: 7068

Change your equals from equals(Word) to equals(Object). Please also add @Override attribute.

Moreover, your hashCode method does not guarantee that for two words that are equal (ignoring case), they will have the same hash code. You can use toUpperCase() on word before computing the hash code.

Upvotes: 2

Related Questions