Like Sean Bright answer, I'd use external Comparator
and if you are working with Java 8, you can do it pretty easily:
public static final Comparator<Foobar> NAME_THEN_AGE =
Comparators.comparing(Foobar::getName, String.CASE_INSENSITIVE_ORDER)
.thenComparing(Foobar::getAge)
;
....
TreeSet<Foobar> foobar = new TreeSet<>(NAME_THEN_AGE);
However, better remaindered that not, it is generally a bad idea to override Comparable
on a child class - perhaps it should be final
on the parent or one should create a protected compareTo0(A)
doing the common work (to avoid comparing object by their parent class).
There are reason for that, and one such is the following (from the Javadoc of Comparable.compareTo):
The implementor must ensure sgn(x.compareTo(y)) ==
-sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an
exception.)
Let's say you have class B
and C
extending A
and A implements Comparable<A>
:
class A implements Comparable<A> {
@Override
public int compareTo(A other) {return ...;}
}
class B extends A {
@Override
public int compareTo(A other) {return compareToAsB(((B)other));}
}
class C extends A {
@Override
public int compareTo(A other) {return compareToAsC(((C)other));}
}
It does not really matter what A::compareTo
returns. Neither what compareToAsB
and compareToAsC
does.
The problem is however here:
A a = ...;
B b = ...;
C c = ...;
a.compareTo(b); // ok
a.compareTo(c); // ok
b.compareTo(a); // ko ClassCastException
b.compareTo(c); // ko ClassCastException
c.compareTo(a); // ko ClassCastException
c.compareTo(b); // ko ClassCastException
As quoted in the javadoc, a.compareTo(b)
should throw a ClassCastException
.
Also, there are part in the Java code (Collections.sort
) where it is important to ensure that sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.