Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generics & Set of Sets

I'm a Java noob with a bit of C++ experience and I'm trying to create a Set of Sets in Java along the following lines (similar to what one would do in C++):

Set< Set< String > > collection = new TreeSet< Set< String > >();
Set< String > entry =  new TreeSet< String >();
collection.add( entry );

This builds fine, but then when the program is executed, a java.util.TreeSet cannot be cast to java.lang.Comparable exception is thrown.

Without reimplementing the wheel, how can one have a Set of Sets in Java?

Also, what is the deal with Java allowing broken code (e.g., the type mismatch) to compile?

Thanks in advance for any feedback.

like image 650
Meh Avatar asked Apr 14 '12 19:04

Meh


People also ask

What are generics in Java?

Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.

Why do we use generics in Java?

In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs.

What is a generic Java class?

A Generic class simply means that the items or functions in that class can be generalized with the parameter(example T) to specify that we can add any type as a parameter in place of T like Integer, Character, String, Double or any other user-defined type.

Should I use generics Java?

Generics should be used instead of raw types ( Collection< T > instead of Collection , Callable< T > instead of Callable , …) or Object to guarantee type safety, define clear type constraints on the contracts and algorithms, and significantly ease the code maintenance and refactoring.


2 Answers

In the contract of TreeSet, the requirement is laid out that all entries have to be Comparable or you have to provide a Comparator. (This is also why you didn't see a compile-time error: entries are only cast to Comparable in the absence of an explicit Comparator.)

It's got nothing to do with generics, it comes from the implementation of TreeSet itself: as it's a binary tree, it only makes sense if the entries can be ordered somehow.

If you tell a bit more about your specific problem, we can probably help you find the exact data structure you need but in general, if you don't care about the order of elements in a set, a HashSet is used. And again, in general, a Set of Sets is often a sign of sloppy design.

like image 174
biziclop Avatar answered Oct 06 '22 02:10

biziclop


If you want to add an object to a TreeSet collection, that object's type must implement the Comparable interface, which TreeSet itself does not. Alternatively, you can provide a Comparator by creating the TreeSet with a different constructor.

It doesn't really make sense to use a TreeSet for this particular scenario because this is by definition an ordered collection and you don't seem to need an ordering of elements. You could try a HashSet instead.

Furthermore, to answer your second question, this error only appears at runtime because you are exploiting polymorphic behavior i.e. you are adding to a Set, which actually at runtime is bound to a TreeSet. This information is not known at compile time.

like image 22
Tudor Avatar answered Oct 06 '22 00:10

Tudor