Lambda表达式官方描述:
One issue with anonymous classes is that if the implementation of your anonymous class is very simple, such as an interface that contains only one method, then the syntax of anonymous classes may seem unwieldy and unclear. In these cases, you're usually trying to pass functionality as an argument to another method, such as what action should be taken when someone clicks a button. Lambda expressions enable you to do this, to treat functionality as method argument, or code as data.
中文释义:
匿名类的一个问题是,如果匿名类的实现非常简单,例如只包含一个方法的接口,那么匿名类的语法可能会显得笨拙和不清楚。 在这些情况下,您通常会尝试将功能作为参数传递给另一个方法,例如当有人单击按钮时应该采取什么操作。 Lambda 表达式使您能够做到这一点,将功能视为方法参数,或将代码视为数据。
个人理解:是针对只有一个方法的匿名类的一个简化语法糖,(jdk1.8新增了一个FunctionalInterface注解,被这个注解注释的接口被称为functional interface 这种接口的实现都可以用lambda表达式)
Lambda表达式语法:
一个 lambda 表达式包含以下内容:
括号中以逗号分隔的形式参数列表。 CheckPerson.test 方法包含一个参数 p,它表示 Person 类的一个实例。
注意:您可以省略 lambda 表达式中参数的数据类型。 另外,如果只有一个参数,可以省略括号。 例如,以下 lambda 表达式也是有效的:
p -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
箭头标记写法,->
主体,由单个表达式或语句块组成。 此示例使用以下表达式:
p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
如果指定单个表达式,则 Java 运行时会计算该表达式,然后返回其值。 或者,您可以使用 return 语句:
p -> {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
return 语句不是表达式; 在 lambda 表达式中,您必须将语句括在大括号 ({}) 中。 但是,您不必将 void 方法调用括在大括号中。 例如,以下是一个有效的 lambda 表达式:
email -> System.out.println(email)
请注意,一个 lambda 表达式看起来很像一个方法声明; 您可以将 lambda 表达式视为匿名方法——没有名称的方法。
以下示例 Calculator 是采用多个形参的 lambda 表达式示例:
public class Calculator {
interface IntegerMath {
int operation(int a, int b);
}
public int operateBinary(int a, int b, IntegerMath op) {
return op.operation(a, b);
}
public static void main(String... args) {
Calculator myApp = new Calculator();
IntegerMath addition = (a, b) -> a + b;
IntegerMath subtraction = (a, b) -> a - b;
System.out.println("40 + 2 = " +
myApp.operateBinary(40, 2, addition));
System.out.println("20 - 10 = " +
myApp.operateBinary(20, 10, subtraction));
}
}
方法operateBinary 对两个整数操作数执行数学运算。 操作本身由 IntegerMath 的实例指定。 该示例使用 lambda 表达式定义了两个运算,即加法和减法。 该示例打印以下内容:
40 + 2 = 42
20 - 10 = 10
Method References(这种双冒号::写法)
您可以使用 lambda 表达式来创建匿名方法。 然而,有时 lambda 表达式除了调用现有方法之外什么都不做。 在这些情况下,按名称引用现有方法通常会更清楚。 方法引用(Method references)使您能够做到这一点; 它们是用于已具有名称的方法的紧凑、易于阅读的 lambda 表达式。
再次考虑 Lambda 表达式部分中讨论的 Person 类:
public class Person {
// ...
LocalDate birthday;
public int getAge() {
// ...
}
public LocalDate getBirthday() {
return birthday;
}
public static int compareByAge(Person a, Person b) {
return a.birthday.compareTo(b.birthday);
}
// ...
}
假设您的社交网络应用程序的成员包含在一个数组中,并且您希望按年龄对数组进行排序。 您可以使用以下代码:
Person[] rosterAsArray = roster.toArray(new Person[roster.size()]);
class PersonAgeComparator implements Comparator<Person> {
public int compare(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
}
Arrays.sort(rosterAsArray, new PersonAgeComparator());
此排序调用的方法签名如下:
static <T> void sort(T[] a, Comparator<? super T> c)
请注意,接口 Comparator 是一个功能接口(functional interface)。 因此,您可以使用 lambda 表达式而不是定义然后创建实现 Comparator 的类的新实例:
Arrays.sort(rosterAsArray,
(Person a, Person b) -> {
return a.getBirthday().compareTo(b.getBirthday());
}
);
但是,这种比较两个 Person 实例的出生日期的方法已经作为 Person.compareByAge 存在。 您可以在 lambda 表达式的主体中调用此方法:
Arrays.sort(rosterAsArray,
(a, b) -> Person.compareByAge(a, b)
);
由于此 lambda 表达式调用现有方法,因此您可以使用方法引用(Method references)而不是 lambda 表达式:
Arrays.sort(rosterAsArray, Person::compareByAge);
方法引用 Person::compareByAge 在语义上与 lambda 表达式 (a, b) -> Person.compareByAge(a, b) 相同。 每个都有以下特点:
它的形参列表是从 Comparator<Person>.compare 复制过来的,即 (Person, Person)。
它的主体调用方法 Person.compareByAge。
附官方文档链接:
https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html