I like the new static factory methods of Comparator
, as they allow to implement Comparators in a very concise and less error-prone way.
But what is the recommended way to implement Comparable
? Should we use Comparators inside the Comparable implementation?
public MyClass implements Comparable<MyClass>{
...
public int compareTo(MyClass other){
Comparator<MyClass> naturalOrderComparator =
Comparator.comparing(MyClass::getFoo)
.thenComparing(MyClass::getBar);
return naturalOrderComparator.compare(this, other);
}
}
or even use a static comparator to reduce a lot of object creation when sorting huge collections:
public MyClass implements Comparable<MyClass>{
private static final Comparator<MyClass> NATURAL_ORDER_COMPARATOR =
Comparator.comparing(MyClass::getFoo)
.thenComparing(MyClass::getBar);
...
public int compareTo(MyClass other){
return NATURAL_ORDER_COMPARATOR.compare(this, other);
}
}
Or is there another recommended way to implement Comparable with Java SE 8?
Pre-Java-8 the general best practice was to use Guava's
ComparisonChain
andOrdering
utilities. They abstract away the cumbersome and easy-to-get-wrong details of properly implementing a.compareTo()
/.compare()
method, and allow you to compose a human-readable sequence of steps to define how objects should be compared.Ordering
implementsComparator
, but there'd be nothing wrong with defining anOrdering
and invoking it in aComparable
's.compareTo()
method.Note that
Ordering
is described as obsolete thanks to the additions to the JDK in Java 8:Your own Option 2 is almost certainly the best currently available way. It avoids allocation, it reads pretty well -- especially if you put the static constant next to the
compareTo
method.The new
Comparator.comparing
factory methods in Java 8 are very easy to read, and even better, difficult to screw up -- there are many, many ways to write comparisons incorrectly by hand, more than I care to remember, and the factory methods are immune to most of them. Even though it's a little weird to use them to write acompareTo
method instead of aComparator
object, it's still better than the alternatives.