Codebender
Codebender

Reputation: 14471

Why is TreeSet declared TreeSet<E> instead of TreeSet<E extends Comparable<E>>

I was working with TreeSet and found a ClassCastException while calling TreeSet#add() method.

Code:

public class Testing {
    public static void main(String[] args) {
        TreeSet<Testing> ts = new TreeSet<>();
        ts.add(new Testing());
    }
}

Output:

Exception in thread "main" java.lang.ClassCastException: Testing cannot be cast to java.lang.Comparable
    at java.util.TreeMap.compare(TreeMap.java:1290)
    at java.util.TreeMap.put(TreeMap.java:538)
    at java.util.TreeSet.add(TreeSet.java:255)
    at Testing.main(Testing.java:13)

Clearly it's because TreeSet is an ordered collection and it needs Comparable objects for ordering them, so why not declare its type as

public class TreeSet<E extends Comparable<E>>

and do the checking during compile time instead of throwing exception at runtime?

Upvotes: 3

Views: 332

Answers (3)

Tagir Valeev
Tagir Valeev

Reputation: 100209

As was mentioned in other answers, TreeSet keys could be not Comparable if custom Comparator is specified. It still would be possible to enforce compile-time check for your case. Suppose that we make the default constructor private and provide a static factory method instead:

public class TreeSet<E> {
    private TreeSet() {...}

    public static <E extend Comparable<? super E>> TreeSet<E> newSet() {
        return new TreeSet<>();
    }
}

This way you would be forced to use TreeSet.newSet() and compile-time type checking would fail if you assign it to TreeSet<Testing> and Testing is not comparable. Why it was not done? Because generics appeared in Java 1.5 only, while TreeSet appeared in Java 1.2, is it was not an issue these times. Now we have to deal with backwards compatibility.

Upvotes: 1

EasterBunnyBugSmasher
EasterBunnyBugSmasher

Reputation: 1582

The way it is implemented, you can order items that cannot decide for themselves if they should be ordered in a higher or lower spot than the "other" item.

Take a real life example: You have a beauty contest. If you ask one of the girls if she is more beautiful than the one next to her, she will say yes. You cannot put them in an order just by asking them. So you need somebody else to be responsible for the ordering, the Comparator.

This allows you to order items that don't have the possibility to compare themselves with another item.

Upvotes: 0

Eran
Eran

Reputation: 393811

A TreeSet's element doesn't have to implement Comparable, since you can pass a Comparator to one of TreeSet's constructors in order to impose an ordering for elements that don't implement Comparable (or for elements that do implement Comparable when you want to use an ordering other than the natural ordering defined by Comparable).

Upvotes: 7

Related Questions