Java - Comparator比较方法的定义class

Java - Definition of the comparing method of Comparator class

我想了解比较器class的方法comparing的定义。我会留下一些代码,以防它有助于解释。我正在使用一个名为 Person 的 class,它基本上存储姓名和姓氏。可以使用 get 方法检索此数据。

public class Person {

    private final String name;
    private final String lastname;

    public Person(String name, String lastname) {
        this.name = name;
        this.lastname = lastname;
    }

    public String getName() { return name; }

    //...
}

然后我创建了一个人员列表:

List<Person> list = Arrays.asList(
    new Person("Juan", "García"),
    new Person("Ana", "Martínez"),
    ...
);

我一直在测试不同的方法来对这个 Persons 列表进行排序。在其他可能性中,我发现了这个:

list.sort(Comparator.comparing(Person::getName));

我明白这些行的作用。基本上,此列表使用比较器排序,该比较器使用排序键(人名)进行比较。使用对属于 Person class.

的 getName 方法的引用来提取此类密钥

不过,我也很想了解幕后的情况。我的问题是 comparing 方法。 Java 文档定义了这样的方法:

static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)

特别是,我正在努力处理泛型类型定义:<T,U extends Comparable<? super U>>;以及参数类型的定义:Function<? super T,? extends U>

T代表比较器类型,而U代表键类型,对吧?所以...为什么 U 需要扩展 Comparable<? super U>,后者又使用 U 的任何 superclass?

在参数中,该函数使用属于 T 的任何 superclass 的对象和 returns 属于 [=] 的任何子 class 的对象21=] (<? super T,? extends U>),但是……为什么?

我希望我的疑问是清楚的。另外,抱歉解释得太长了。

让我们考虑上述方法的签名 comparing static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)

  • T 是被比较对象的类型,在上述情况下是 Person

  • U extends <Comparable<? super U>> 描述了用于实现实际比较的类型 - 这就是为什么这种类型必须是 Comparable - 在这种情况下它是 String

  • Function<? super T,? extends U> keyExtractor - keyExtractor 是一个将 class T (Person) 的对象“转换”为可比较对象的函数class U (String) - 在此 class 中,它是 getter class Person 中定义的名称。

我在这里看到三个主要的困惑:

为什么 U extends Comparable<? super U>

这是对 U(键的类型)的约束,指定了 U 可以是什么特定类型。它说 U 必须具有可比性。有道理,对吧?尖括号中的部分指定“U 可以比作什么?”例如,Comparable<Animal> 表示“堪比动物”。约束表示“U 必须与 U 的某些超类型相当”。

您可能想知道为什么它不直接说“U 必须与 U 相当”,即 U extends Comparable<U>。这是因为我们试图使我们的方法尽可能灵活,即我们尝试接受尽可能多的不同 U。如果我有一个可以与 Animal(实现 Comparable<Animal>)进行比较的 Dog,那么狗也可以与另一个 Dog 进行比较是合乎逻辑的。然而,由于 Dog 实现了 Comparable<Animal> 而不是 Comparable<Dog>,它不满足 U extends Comparable<U>,这就是为什么我们必须使用 U extends Comparable<? extends U>.

为什么 Function 需要 ? super T

假设我有一个密钥提取器,它接受一个 Object,我 return 它的 toString() 输出作为要比较的密钥(这是一个非常不常见的比较,但是为了这个例子,请耐心等待 :D)

Function<Object, String> stringExtractor = Object::toString;

现在我想要一个比较动物的比较器。我可以使用这个 stringExtractor 作为 comparing 的参数吗?我当然可以:

Comparator<Animal> comparator = Comparator.comparing(stringExtractor);

所有动物都有toString方法,毕竟它们是Object的子类!这就是为什么关键提取器参数采用采用超类 T 的函数的原因 - 以允许我们传递上述内容。如果是Function<T, ? extends U>,我们就做不到Comparator.comparing(stringExtractor).

同样,我们的想法是 comparing 处理尽可能多的东西。

为什么 Function return ? extends U?

这其实是没有必要的。除非你像这样明确指定 TU

Comparator.<Foo, Animal>comparing(Foo::getDog);

Function<? super T, U>Function<? super T, ? extends U>没有区别。有关详细信息,请参阅 。这个问题是关于 thenComparing,它的签名是 comparing.