Consider the following example where we are sorting people based on their last name:
public class ComparatorsExample {
public static class Person {
private String lastName;
public Person(String lastName) {
this.lastName = lastName;
}
public String getLastName() {
return lastName;
}
@Override
public String toString() {
return "Person: " + lastName;
}
}
public static void main(String[] args) {
Person p1 = new Person("Jackson");
Person p2 = new Person("Stackoverflowed");
Person p3 = new Person(null);
List<Person> persons = Arrays.asList(p3, p2, p1);
persons.sort(Comparator.comparing(Person::getLastName));
}
}
Now, let's assume that getLastName returns an optional:
public Optional<String> getLastName() {
return Optional.ofNullable(lastName);
}
Obviously persons.sort(Comparator.comparing(Person::getLastName)); will not compile since Optional (the type getLastName returns) is not a comparable. However, the value it holds is.
The first google search points us in this answer. Based on this answer we can sort persons by doing:
List<Person> persons = Arrays.asList(p3, p2, p1);
OptionalComparator<String> absentLastString = absentLastComparator(); //type unsafe
persons.sort((r1, r2) -> absentLastString.compare(r1.getLastName(), r2.getLastName()));
My question is, is it possible to have this kind of sorting using a function (key extractor) just like Comparator.comparing?
I mean something like (without caring absent values first or last):
persons.sort(OptionalComparator.comparing(Person::getLastName));
If we look into Comparator.comparing, we see the following code:
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable) (c1, c2) -> {
return keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
};
}
I tried multiple ways to make it return an OptionalComparator instead of a simple Comparator, but everything I tried and made sense to me was unable to be compiled. Is it even possible to achieve something like that? I guess type-safety cannot be achieved, since even Oracle's comparing throws a type-safety warning.
I am on Java 8.