How to sort a list of generic types in Java
Solution 1
Use an intersection type, like this:
public class MyList<T extends BaseEntity & Comparable<T>> {...}
That specifies that T must be both a BaseEntity
and Comparable
to itself.
Solution 2
Don't use Collections.sort(List<T>)
, use Collections.sort(Lst<T>, Comparator<? extends T>)
instead. Write the comparation code in the comparator.
Solution 3
Try this:
static <T extends Comparable<? super T>> sort(T[] array);
This is the most general specification to accomplish the task. Basically, it asserts, that T is a type which can be compared to itself.
Dave Mulligan
Updated on July 25, 2022Comments
-
Dave Mulligan almost 2 years
I have a set of classes that all share some common attributes, so I made them all extend a common base class,
BaseEntity
. So I have, for exampleFoo extends BaseEntity
andBar extends BaseEntity
.I also want lists of these
Foo
andBar
objects to be sortable, so I have implementedComparable
. I have the classes defined asFoo extends BaseEntity implements Comparable<Foo>
andBar extends BaseEntity implements Comparable<Bar>
, and sorting of lists ofFoo
s orBar
s works as expected - and, of course, the details of the sorting are different in the different subclasses. But I can't work out how to make my sorting work when I don't know in advance whether I'll haveFoo
s orBar
s. This code, for example, fails to compile:public class UtilityClass<T extends BaseEntity> { ...bunch of stuff... List<T> values; public List<T> sort() { Collections.sort(values); return values; } ...more methods... }
with the error message
Bound mismatch: The generic method sort(List<T>) of type Collections is not applicable for the arguments (List<T>). The inferred type T is not a valid substitute for the bounded parameter <T extends Comparable<? super T>>
I think the problem is that I am attempting to sort a list of
BaseEntity
objects, andBaseEntity
itself doesn't implementComparable
. But now I face a problem: the only sensible thing to makeBaseEntity
objects comparable to is otherBaseEntity
objects, but when I addimplements Comparable<BaseEntity>
toBaseEntity
, the compiler tells me that I've got problems now because myFoo
class is trying to implement bothComparable<BaseEntity>
andComparable<Foo>
, which evidently is not allowed.I know I could sidestep this issue by dropping the
implements Comparable<Foo>
and just implementingComparable<BaseEntity>
, but then mycompareTo
methods will have to do ugly casting, and I thought that was exactly the sort of problem using generics was supposed to avoid.What I really want to do is specify in the signature of
BaseEntity
that all its subclasses will beComparable
, but only to instances of the same subclass.Any assistance gratefully received. Thanks!
-
Dave Mulligan over 11 yearsThe
MyList
class was just an example to show the error message. I chose a bad name :-(, this isn't actually a list of anything and instances of this class just need to perform the sorting, not actually be sortable themselves. -
Dolda2000 over 11 yearsI don't see why that would change the applicability of the answer, though. :)
-
notXX over 11 yearsbecause generics in java 5 is lame. the error 'like trying to implement both
Comparable<BaseEntity>
andComparable<Foo>
, which evidently is not allowed' obviously suggested it. -
Dave Mulligan over 11 yearsOh, yes, you're right. That
Comparable<T>
applies toT
, not toMyList
. Thank you thank you thank you. -
newacct over 11 yearsfor best results, use
<T extends BaseEntity & Comparable<? super T>>
-
Tushar Banne over 6 years@newacct cn u explain what <T extends BaseEntity & Comparable<? super T>> actually does?
-
newacct over 6 years@TusharBanne:
Comparable
is a consumer and so should always be used with? super
wildcards, according to the PECS rule. Without the? super
wildcard, if you have a class that is comparable to itself, its subclass cannot be used asT
here, even though it should be able to.