lambda表达式通常用匿名方法。而有时候,lambda表达式做的仅仅是调用一个已经存在的方法,可以通过函数名调用该函数,即method reference。
以数组排序为例:
pubic class Person {
public static int compareByAge(Person a, Person b) {
return a.birthday.compareTo(b.birthday);
}
}
Person[] personArray = ...
class PersonAgeComparator implements Comparator<Person> {
...
}
对personArray
排序
Arrays.sort(personArray, new PersonArayComparator());
该sort函数的签名是:
static <T> void sort(T [] a, Comparator<? super T> c)
functional interface
因为Comparator
是一个函数接口(functional interface),因此可以用lambda替换:
Arrays.sort(personArray, (a,b) -> Person.compareByAge(a, b));
method reference
又可以通过函数名调用该函数,替换后的lambda:
Arrays.sort(personArray, Person::compareByAge);
两种已经存在的函数的lambda表达式,method reference和functional interface:
Person::compareByAge和(a,b)->Person.compareByAge(a,b)
四种Method references
类型 | 表达式 |
---|---|
静态方法 | FooClass::staticMethodName |
特定对象的实例方法 | fooObject::instanceMethodName |
特定类型的任意对象的实例方法 | FooClass::instanceMethodName |
constructor | FooClass::new |
引用静态方法
Person::compareByAge
引用特定对象的实例方法
class ComparisonProvider {
public int compareByName(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
ComparisonProvider obj = new ComparisonProvider();
Arrays.sort(rosterAsArray, obj::compareByName)
method reference obj::compareByName
调用obj对象的compareByName方法,JRE推断出它的参数类型。这个例子中是(Person, Person)
引用特定类型的任意对象的实例方法
String[] stringArray = {"A", "B", "C"};
Arrays.sort(stringArray, String::compareToIgnoreCase);
method reference String::compareToIgnoreCase
等效的lambda表达式参数列表(String a, String b)
,其中a和b是任意的名字。method reference会调用方法a.compareToIgnoreCase(b)
Constructor
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;
}
functional interface Supplier
包含一个方法get
,get
方法没有参数并且返回一个对象,因此可以用lambda表达式调用函数transferElements
:
Set<Person> rosterSetLambda = transferElements(roster, () -> {return new HashSet<>();});
也可以用一个constructor reference替代lambda的位置:
Set<Person> rosterSet = transferElements(roster, HashSet::new);
编译器推断出你想要创建一个HashSet元素的类型是Person
,也可以指定类型为Person
:
transferElements(roster, HashSet<Person>::new);
关键词:已经存在的方法;lambda