I'm not sure where you plan to put Comparator . Since you want your class to implement Comparable<Organism> , I assume you are looking for something like
class Bacteria implements Organism { enum Shape {ROD, ROUND, SPIRAL}; private final Shape shape; Comparator<Organism> comparator = Comparator .comparingInt(Organism::getComplexity) .thenComparing(Bacteria::shape);
This will not work, because thenComparing , in the context, needs a Function parameter that works with Organism , not Bacteria . You can get around this this way: I will leave it to you to decide if it is elegant enough:
Comparator<Organism> comparator = Comparator .comparingInt(Organism::getComplexity) .thenComparing(x -> ((x instanceof Bacteria) ? ((Bacteria)x).getShape() : Shape.ROD));
In theory, you can also write your own method, which can convert a comparator to another. You cannot use the notation instance.method , so the use should be something like this:
Comparator<Organism> comparator = MyComparatorUtilities.thenComparingIfInstanceOf( Comparator.comparingInt(Organism::getComplexity), Bacteria.class, Bacteria::getShape);
The following implementation of thenComparingIfInstanceOf compiles (and allows you to compile the code above), but I have not tried to test it:
class MyComparatorUtilities { public static <T,U extends T,V extends Comparable<? super V>> Comparator<T> thenComparingIfInstanceOf( Comparator<T> comparator, Class<U> subclass, Function<? super U, ? extends V> keyExtractor) { return (a, b) -> { int comp = comparator.compare(a, b); if (comp != 0) { return comp; } if (subclass.isInstance(a) && subclass.isInstance(b)) { return keyExtractor.apply(subclass.cast(a)) .compareTo(keyExtractor.apply(subclass.cast(b))); } return 0; }; } }
MORE : To answer the comment: no, I do not necessarily think that this approach is more readable or supported. In fact, I believe that the whole project is unattainable because it is too easy to add a class that will cause the comparison to violate the properties of full ordering; I would look for a different design, starting with a clearer definition of how I want the order to work on objects of different classes. The βrightβ way to handle comparisons is likely to depend on this other design.
For such problems, I can take the compareTo approach, unless I need a class to return Comparator for some other reason (for example, for Organism s) there are several orders. However, I could look for ways to eliminate duplication if each compareTo is an if with the same structure or something like that.