Рассмотрим следующий пример, в котором мы сортируем людей по фамилии:
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));
}
}
Теперь предположим, что getLastName
возвращает необязательное значение:
public Optional<String> getLastName() {
return Optional.ofNullable(lastName);
}
Очевидно persons.sort(Comparator.comparing(Person::getLastName));
не будет компилироваться, поскольку Optional
(возвращается тип getLastName
) не является сопоставимым. Однако его значение равно.
Первый поиск Google указывает нам на этот ответ . Основываясь на этом ответе, мы можем отсортировать людей, выполнив:
List<Person> persons = Arrays.asList(p3, p2, p1);
OptionalComparator<String> absentLastString = absentLastComparator(); //type unsafe
persons.sort((r1, r2) -> absentLastString.compare(r1.getLastName(), r2.getLastName()));
Мой вопрос: можно ли использовать такую сортировку с использованием функции (экстрактора ключей), как Comparator.comparing?
Я имею в виду что-то вроде (не заботясь об отсутствующих значениях первым или последним):
persons.sort(OptionalComparator.comparing(Person::getLastName));
Если мы посмотрим на Comparator.comparing , мы увидим следующий код :
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));
};
}
Я пробовал несколькими способами заставить его возвращать OptionalComparator
вместо простого Comparator
, но все, что я пробовал и имело для меня смысл, не могло быть скомпилировано. Возможно ли вообще что-то подобное? Я полагаю, что типобезопасность не может быть достигнута, поскольку даже Oracle comparing
выдает предупреждение о типобезопасности.
Я на Java 8.