gpt4 book ai didi

java - 带有 key 提取器的 Optional 比较器,如 java.util.Comparator.comparing

转载 作者:行者123 更新时间:2023-12-01 10:22:02 24 4
gpt4 key购买 nike

考虑以下示例,其中我们根据姓氏对人员进行排序:

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返回一个 optional :
public Optional<String> getLastName() {
return Optional.ofNullable(lastName);
}

显然 persons.sort(Comparator.comparing(Person::getLastName));不会编译,因为 Optional (类型 getLastName 返回)不是可比的。然而,它所拥有的值(value)是。

第一个谷歌搜索将我们指向 this answer .基于此答案,我们可以通过以下方式对人员进行排序:
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 上。

最佳答案

您可以使用 Comparator#comparing(Function,Comparator) :

Accepts a function that extracts a sort key from a type T, and returns a Comparator<T> that compares by that sort key using the specified Comparator.



这是基于您问题中的代码的示例:

persons.sort(comparing(Person::getLastName, comparing(Optional::get)));

基本上这是使用嵌套的 key 提取器来最终比较 String代表姓氏的对象。请注意,这将导致 NoSuchElementException如果 Optional 被抛出是空的。您可以创建一个更复杂的 Comparator处理空 Optional s1:

// sort empty Optionals last
Comparator<Person> comp =
comparing(
Person::getLastName,
comparing(opt -> opt.orElse(null), nullsLast(naturalOrder())));
persons.sort(comp);

如果您需要经常这样做,请考虑以类似于 Comparator#nullsFirst(Comparator) 的方式创建实用程序方法。和 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));
}

然后可以像这样使用:

persons.sort(comparing(Person::getLastName, emptyLast()));

1.根据 @Holger提供的建议简化示例代码.如果好奇,请查看编辑历史记录以查看代码之前的样子。

关于java - 带有 key 提取器的 Optional<T> 比较器,如 java.util.Comparator.comparing,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61681709/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com