如何解释方法比较的参数(Function<? super T,? extends U> keyExtractor)?

How do I interpret the argument of method comparing(Function<? super T,? extends U> keyExtractor)?

方法的完整签名:

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

我正在学习 lambda 表达式,我有这段代码比较员工列表并按名称字段对它们进行排序:

List<Employee> employees = new ArrayList<>();

Collections.sort(employees, Comparator.comparing(Employee::getName));

代码工作正常,但我查看了文档中的 Comparator 功能接口,发现了方法“comparing()”的签名。

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

我没有得到 comparing() 的参数。我怎么知道参数接受 lambda 表达式?以及如何解释约束: keyExtractor?

我知道 super 是什么意思?在分层继承中必须是 T 或以上类型,并且 ?在层次继承中也必须是 U 及以下类型。但是我们怎么能在我的例子中引用它呢?

可以这样解读: ?在继承链中必须是 Employees 及以上类型,并且 name 字段在继承链中必须是 Employees 或以下类型?要么 ?必须是 Array List 及以上类型和 ?必须输入 Employees List 及以下?

How do I know that the parameter accepts a lambda expersion?

通过查看它接受的参数的 interface。在这种情况下,参数类型是 Function,它是一个 功能接口 (这个名称实际上与接口名称没有任何联系 - 你可以命名你的接口随你怎么便)。 功能接口是一个interface,只有一个未实现的功能(额外的区别来自interface s 可以有 default 个实现)。

看看Function:

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

只有 一个 未实现的方法 - 它被称为 apply。当您创建一个应该是 Function 的 lambda 时,该 lambda 的主体将用于实现 apply.

您可能对 @FunctionalInterface 感到困惑 - 它不是必需的。这只是为了方便起见的注释。


关于<? super T,? extends U>,这些是对泛型类型的约束。这意味着 said Function 需要一个超类型 T 的参数,并将 return 从 U 派生的东西。这是一个相当复杂的话题。你可以 read more about it here.

方法的完整签名:

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

Citing from docs:

Accepts a function that extracts a Comparable sort key from a type T, and returns a Comparator that compares by that sort key.

所以,到目前为止,我们知道 comparing() 方法接受一个函数作为参数,这是一个函数式接口,@Fureeish 在之前的回答中已经解释过了。因为 lambda 表达式是围绕功能接口构建的,我们知道我们可以将它用作参数。

类型参数:

T - the type of element to be compared U - the type of the Comparable sort key

T,在上面的定义中是Employee类型,因为我们要比较employee或对象的类型,他们的class是Employee的超classes。 ?超级 T,意味着占位符?在继承链中必须是 T 或以上类型。

U,是String类型,是name字段,String实现了Comparable(see docs),至于方法定义:

public static <T, U extends Comparable<? super U>> Comparator

参数方法return一个通过提取的键进行比较的比较器。