函数接口作为函数引用

时间:2017-09-05 10:12:36

标签: java function java-8 method-reference

public static void main(String o[]) {
    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("a", 1);
    map.entrySet().stream().sorted(Comparator.comparing(Entry::getValue)).forEach(System.out::println);
}

上面的代码构建和运行完美,但它不应该。 Comparator.comparing采用函数引用,只有那些接受一个参数并返回一个参数的方法才能映射到此。但是在上面的代码中,getValue被映射并且工作正常,但它没有采用任何参数。代码应该给出构建问题,但不是。我的概念有什么问题吗?

2 个答案:

答案 0 :(得分:5)

单个参数comparing方法:

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

采用Function<? super T, ? extends U>参数,这是一个函数接口,它包含一个方法,该方法接受一种类型的参数并返回其他类型的值。

Entry::getValue接受一种类型的参数(在您的示例中为Map.Entry<String, Integer>)并返回其他类型的值(示例中为Integer)。因此它匹配Function功能接口。

  

但是在上面的代码中,getValue被映射并且工作正常,但它没有采用任何参数。

是的 - 从Map.Entry获取的每个Stream元素都充当apply()接口的Function方法的参数。

也许这会澄清:

Function<Map.Entry<Integer, String>, String> func = Map.Entry::getValue;

getValue() Map.Entry方法可被视为Function接受Map.Entry实例并返回该实例的值(通过调用{{1}返回)在那个实例上)。

答案 1 :(得分:2)

在这种情况下,您的方法引用是一个实例方法,而不是静态方法,因此不是为每个项调用并使用以下值:

getValue()

使用

Entry.getValue(item) [JavaDoc的] (https://docs.oracle.com/javase/7/docs/api/java/util/Map.Entry.html#getValue()

所以它充当lambda:item.getValue(),将一个条目转换为它的值进行比较,因为它有一个参数并返回一个值而不抛出它可以实现的异常p -> p.getValue()

如果静态和实例方法都存在,则无法使用方法引用,如此问题:Link

Worked example