Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a TreeSet with a non-Comparable class: why a run-time exception, rather than compile-time error?

If I create an arbitrary class that does not implement Comparable, and try to use it as a treeset, it throws an exception at run time when an object is inserted:

public class Foo {
}

public TreeSet<Foo> fooSet = new TreeSet<Foo>();
fooSet.add(new Foo()); // Throws a ClassCastException exception here: Foo is not comparable

I'm no Java expert, but something about this seemed dynamically typed (ala Python) in a way I wasn't expecting. Is there no way for TreeSet's implementation to specify that its generic type argument must implement Comparable so that this can be caught at compile-time? Non-generic functions can take interfaces as arguments; is the same not possible with generics?

like image 343
uscjeremy Avatar asked Dec 15 '12 08:12

uscjeremy


People also ask

Why do we get Classcastexception in TreeSet?

This error is thrown by TreeSet because TreeSet is used to store elements in sorted order and if the specified element cannot be compared with the elements currently in the set then TreeSet won't be able to store elements in sorted order and hence, TreeSet throws class cast exception.

Does TreeSet use comparable?

The elements in TreeSet must be of a Comparable type. String and Wrapper classes are Comparable by default. To add user-defined objects in TreeSet, you need to implement the Comparable interface.

Why heterogeneous objects are not allowed in TreeSet?

TreeSet does not allow to insert heterogeneous objects because it must compare objects to determine sort order. TreeSet is not synchronized. If multiple threads access a hash set concurrently, and at least one of the threads modifies the set, it must be synchronized externally.

Will TreeSet allow duplicates?

TreeSet implements the SortedSet interface. So, duplicate values are not allowed and will be leftovers. Objects in a TreeSet are stored in a sorted and ascending order. TreeSet does not preserve the insertion order of elements but elements are sorted by keys.


1 Answers

TreeSet is implemented that way because you can alternatively provide a Comparator, in which case the elements don't need to be Comparable. The only way to support both behaviors without splitting the implementation into multiple classes was to include runtime checks - this was simply a design decision by the author(s) of that class.

Exposing factory methods for TreeSet instead of public constructors would've been a way to maintain compile time checks using stricter generic type constraints, but that would've been a break from the core collections API's convention of exposing public no-arg and copy constructors for its implementation classes. As you noted in your comment, Guava goes the factory route with its collections and IMHO is better off for it.

like image 176
Paul Bellora Avatar answered Sep 19 '22 10:09

Paul Bellora