考虑下面的示例,我们将根据他们的姓氏对他们进行排序:
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搜索将我们指向this answer。基于此答案,我们可以通过执行以下操作对人员进行排序:
List<Person> persons = Arrays.asList(p3, p2, p1);
OptionalComparator<String> absentLastString = absentLastComparator();
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。
您可以使用Comparator#comparing(Function,Comparator)
:
[接受从类型
Comparator#comparing(Function,Comparator)
中提取排序键,然后返回T
的函数,该功能使用指定的Comparator<T>
与该排序键进行比较。
这是一个基于您的问题代码的示例:
Comparator
基本上,这是使用嵌套的键提取器来最终比较代表姓氏的persons.sort(comparing(Person::getLastName, comparing(Optional::get));
对象。请注意,如果其中一个String
为空,则将引发NoSuchElementException
。