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.

Category >> Collections  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • 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!

  • Yishagerew lulie

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

  • By default elements are stored in TreeSet using natural ordering. If you want to sort using different order then you need to provide your own comparator.

    If you want to sort a TreeSet of Strings in descending order there is an example here – http://netjs.blogspot.com/2015/10/how-to-sort-elements-in-different-order-tree-set-java.html

  • asdf

    asdfg

  • Mohammed

    Very Useful…

  • Ruchika

    Thanks.. was looking for the same thing