Implement Comparable for a TreeSet

The first example below shows a common mistake when an object is added to a set. Because every element in a set much be unique, any object must be compared with the objects in the set already before it is added.

1. Common Mistake of Comparable Interface

First take a took at the following code which create 3 dogs and add those dogs to a TreeSet.

import java.util.TreeSet;
 
class Dog {
    int size;
    Dog(int s) {
        size = s;
    }
}
 
public class ImpComparableWrong {
 
    public static void main(String[] args) {
        TreeSet<Integer> i = new TreeSet<Integer>();
        TreeSet<Dog> d = new TreeSet<Dog>();
        d.add(new Dog(1));
        d.add(new Dog(2));
        d.add(new Dog(1));
 
        i.add(1);
        i.add(2);
        i.add(3);
 
        System.out.println(d.size() + &quot; &quot; + i.size());
    }
}

The output is:

run:

Exception in thread "main" java.lang.ClassCastException: Dog cannot be cast to java.lang.Comparable
        at java.util.TreeMap.put(TreeMap.java:542)
        at java.util.TreeSet.add(TreeSet.java:238)
        at ImpComparableWrong.main(ImpComparableWrong.java:17)
Java Result: 1
BUILD SUCCESSFUL (total time: 2 seconds)

The reason is that Class Dog needs to implement Comparable in order for a TreeSet (which keeps its elements sorted) to be able to contain Dog objects. The added object cannot be compared with the elements currently in the set, the add(Object) call throws a ClassCastException. To make an object comparable, user-defined class must implement the Comparable interface.

2. Solution for implementing Comparable for a TreeSet

The following is the code corrected (which implements Comparable):

import java.util.TreeSet;
 
class Dog implements Comparable<Dog> {
 
    int size;
 
    Dog(int s) {
        size = s;
    }
 
    public int compareTo(Dog o) {
        return size - o.size;
    }
}
 
public class ImpComparable {
 
    public static void main(String[] args) {
 
        TreeSet<Dog> d = new TreeSet<Dog>();
        d.add(new Dog(1));
        d.add(new Dog(2));
        d.add(new Dog(1));
 
        TreeSet<Integer> i = new TreeSet<Integer>();
        i.add(1);
        i.add(2);
        i.add(3);
 
        System.out.println(d.size() + &quot; &quot; + i.size());
    }
}

Output:

run:
2 3
BUILD SUCCESSFUL (total time: 0 seconds)

3. Comparator vs. Comparable

Check out the comparision and figure out when to use which.

6 thoughts on “Implement Comparable for a TreeSet”

  1. J’aime juste les informations précieuses que vous fournissez sur vos articles.
    Je mettrai un signet sur votre blog et je testerai de nouveau fréquemment ici.
    Je suis certain que l’on me dira plein de nouvelles choses ici même!
    Bonne chance pour la suite!

  2. There are actually various ways to implement a comparator inside a class without implementing the comparator interface, here is one.

    class Dog{
    // other sections of the code ommitted
    public static final Comparator dogSize = new Comparator(){
    @Override
    public int compareTo(Dog o) {
    return size - o.size;
    }
    }
    }

    And in the main method, you can use it as


    TreeSet d = new TreeSet(Dog.dogSize);

Leave a Comment