Comparator for Optional<T> with key extractor, like java.util.Comparator.comparing
You can use Comparator#comparing(Function,Comparator)
:
Accepts a function that extracts a sort key from a type
T
, and returns aComparator<T>
that compares by that sort key using the specifiedComparator
.
Here's an example based on the code in your question:
persons.sort(comparing(Person::getLastName, comparing(Optional::get)));
Basically this is using nested key extractors to ultimately compare the String
objects representing the last names. Note this will cause a NoSuchElementException
to be thrown if either Optional
is empty. You can create a more complicated Comparator
to handle empty Optional
s1:
// sort empty Optionals last
Comparator<Person> comp =
comparing(
Person::getLastName,
comparing(opt -> opt.orElse(null), nullsLast(naturalOrder())));
persons.sort(comp);
If you need to do this a lot then consider creating utility methods in a manner similar to Comparator#nullsFirst(Comparator)
and Comparator#nullsLast(Comparator)
1:
// empty first, then sort by natural order of the value
public static <T extends Comparable<? super T>> Comparator<Optional<T>> emptyFirst() {
return emptyFirst(Comparator.naturalOrder());
}
// empty first, then sort by the value as described by the given
// Comparator, where passing 'null' means all non-empty Optionals are equal
public static <T> Comparator<Optional<T>> emptyFirst(Comparator<? super T> comparator) {
return Comparator.comparing(opt -> opt.orElse(null), Comparator.nullsFirst(comparator));
}
// empty last, then sort by natural order of the value
public static <T extends Comparable<? super T>> Comparator<Optional<T>> emptyLast() {
return emptyLast(Comparator.naturalOrder());
}
// empty last, then sort by the value as described by the given
// Comparator, where passing 'null' means all non-empty Optionals are equal
public static <T> Comparator<Optional<T>> emptyLast(Comparator<? super T> comparator) {
return Comparator.comparing(opt -> opt.orElse(null), Comparator.nullsLast(comparator));
}
Which can then be used like:
persons.sort(comparing(Person::getLastName, emptyLast()));
1. Example code simplified based on suggestions provided by @Holger. Take a look at the edit history to see what the code looked like before, if curious.