我们使用lambda表达式创建了一个匿名函数,也就是利用lambda表达式来直接指定函数要实现的功能,但是有时候lambda表达式并不做任何事情,而只是调用一个现有的方法,例如下面这个对对象型数组进行排序的例子:
public class Main { public static void main(String[] args) { Person[] pers = {new Person(12, "h1"), new Person(23, "h2"), new Person(14, "h3"), new Person(2, "h4")}; Arrays.sort(pers,(a,b)->{return a.getAge()-b.getAge();}); Arrays.stream(pers).forEach(obj -> System.out.print(obj + " ")); } } @Data @ToString class Person{ int age; String name; public Person(int age,String name){ this.age=age; this.name=name; } public static int compareByAge(Person a,Person b){ return a.age-b.age; } }
上一节已经总结了,Arrays.sort的参数是T[] a, Comparator<? super T> c,其中Comparator是一个函数式接口,可用lambda表达式指定其实现结构:(a,b)->{return a.getAge()-b.getAge();},但是这个方法实现已经在Person中定义了,也就是compareByAge方法,所以我们的排序也可以这样指定:
public class Main { public static void main(String[] args) { Person[] pers = {new Person(12, "h1"), new Person(23, "h2"), new Person(14, "h3"), new Person(2, "h4")}; Arrays.sort(pers,(a,b)->Person.compareByAge(a,b)); Arrays.stream(pers).forEach(obj -> System.out.print(obj + " ")); } }
上面的lambda表达式触发一个已经存在的方法,所以也可以使用方法引用(method reference)的形式来代替lambda表达式:
Arrays.sort(pers,Person::compareByAge);
上面的语法形式就是方法引用,有四种形式的方法引用,如下图:
下面的代码将前三种类型的方法引用展示了出来:
public class MethodReferenceExample { public static <T> T mergeThings(T a, T b, BiFunction<T,T,T> merger){ return merger.apply(a,b); } public static String appendString(String a,String b){ return a+b; } public String appendString2(String a,String b){ return a+b; } public static void main(String[] args) { MethodReferenceExample methodReferenceExample=new MethodReferenceExample(); //利用lambda表达式实现功能 System.out.println(MethodReferenceExample.mergeThings("ab","cd",(a,b)->a+b)); //利用静态方法引用实现功能 System.out.println(MethodReferenceExample.mergeThings("ab","cd",MethodReferenceExample::appendString)); //利用实例方法引用实现功能 System.out.println(MethodReferenceExample.mergeThings("ab","cd",methodReferenceExample::appendString2)); //利用对象所属类型的实例方法引用实现功能,下面的待合并的对象都是字符串,可引用String的实例方法concat实现功能 System.out.println(MethodReferenceExample.mergeThings("ab","cd",String::concat)); } }
又如:
String[] strArray={"Barbara","James","Mary","John","Patricia","Robert","Michael","Linda"};
Arrays.sort(strArray,String::compareToIgnoreCase);
构造方法引用实例如下:
public static <T,SOURCE extends Collection<T>,DEST extends Collection<T>> DEST transferElements(SOURCE src, Supplier<DEST> des){ DEST result=des.get(); for(T t:src){ result.add(t); } return result; } public static void main(String[] args) { String[] strArray={"Barbara","James","Mary","John","Patricia","Robert","Michael","Linda"}; List<String> src= Arrays.asList(strArray); //使用lambda表达式创建ArrayList对象 List<String> res2= transferElements(src, ()-> new ArrayList<>()); //使用构造方法引用创建ArrayList对象 List<String> res1= transferElements(src, ArrayList::new); }
上面的代码使用构造方法引用创建ArrayList对象,有了方法引用,Lambda表达式的使用更为简练了