首页 > 代码库 > Java:函数引用

Java:函数引用

你可以Lambda表达式去创建匿名的方法。但很多时候,这份方法可能是已经存在的,这时你可以使用函数引用。这样能够使代码结构更清晰。


我们知道,贪心算法里面,一个常见的步骤是排序。假设有下面的背包类:

class Package{

    private int weight;
    // ignore setter and getter
}

我们有个背包数组 Package[] packages,如果要对其排序:

Arrays.sort(packages,
          new Comparator<Package>(){
          public int compare(Package a,Package b){

         return Integer.valueOf(a.getWeight()).compareTo(Integer.valueOf(b.getWeight()));
  }
});

熟悉Lambda表达式的朋友一眼就看到,Comparator就是一个函数接口。这样,可以改为:

Arrays.sort(packages,
     (Package a,Package b) ->{
       return Integer.valueOf(a.getWeight()).compareTo(Integer.valueOf(b.getWeight());
});

现在,我们设想,如果Package类有个静态方法是这样的:

public static int compageW(Package a,Package b){
   return Integer.valueOf(a.weight).comPareTo(Integer.valueOf(b.weight));
}


这时,可以把Lambda表达式的Body部分改为:

Arrays.sort(packages,
      (a,b) -> Person.compareW(a,b));


因为,lambda表达式引用的是已经存在的函数,我们就可以使用函数引用。

Arrays.sort(packages,Person::caompareW);


前面的例子是 对静态函数的引用。Java8还支持对特定类型实例方法的引用对一种类型的任意对象函数引用对构造器的引用


对特定对象实例方法的引用也很简单,假设前面的compareW方法不是static的。

我们可以使用,

Package p = new Package();
Arrays.sort(packages,
                p::compareW);


对特定类型实例方法的引用,如,

String[] stringArray = { "Barbara", "James", "Mary", "John",
    "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);


对构造器的引用,

这个例子来自Oracle的教程,是完成两个集合之间的复制。

public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>
    DEST transferElements(
        SOURCE sourceCollection,
        Supplier<DEST> collectionFactory) {
        
        DEST result = collectionFactory.get();
        for (T t : sourceCollection) {
            result.add(t);
        }
        return result;
}

Supplier是个函数接口,仅有get方法来获取对象。

你的调用可能是,

Set<Person> rosterSetLambda =
    transferElements(roster, () -> { return new HashSet<>(); });
可以使用函数引用简化,

Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);


最后,简单说明一下Supplier接口:

This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.





Java:函数引用