需要熟悉的基础概念
在 JDK 8 添加 Lambda 表达式支持之前,我只在C++ 等语言中使用了它们的示例。
将此功能添加到 Java 后,我开始更深入地研究它们。
添加 lambda 表达式会增加语法元素,从而增强 Java 的表达能力。在本文中,我想重点介绍您需要熟悉的基础概念,以便您可以立即开始将 lambda 表达式添加到您的代码中。
快速介绍
Lambda 表达式利用了多核环境的并行处理能力,正如在 Stream API 中对数据的管道操作的支持所看到的那样。
它们是匿名方法(没有名称的方法),用于实现由功能接口定义的方法。在接触 lambda 表达式之前,了解什么是函数式接口很重要。
功能接口
功能接口是包含一个且仅一个抽象方法的接口。
如果你看一下 Java 标准Runnable 接口的定义,你会注意到它是如何落入功能接口的定义中的,因为它只定义了一个方法:run()
.
在下面的代码示例中,该方法computeName
是隐式抽象的,并且是唯一定义的方法,从而形成MyName
了一个功能接口。
interface MyName{
String computeName(String str);
}
箭头运算符
Lambda 表达式将新的箭头运算符->
引入 Java。它将 lambda 表达式分为两部分:
(n) -> n*n
左侧指定表达式所需的参数,如果不需要参数,也可以为空。
右侧是 lambda 主体,它指定 lambda 表达式的操作。将此运算符视为“成为”可能会有所帮助。例如,“n 变为 n*n”或“n 变为 n 平方”。
考虑到函数式接口和箭头运算符的概念,您可以组合一个简单的 lambda 表达式:
interface NumericTest {
boolean computeTest(int n);
}
public static void main(String args[]) {
NumericTest isEven = (n) -> (n % 2) == 0;
NumericTest isNegative = (n) -> (n < 0);
// Output: false
System.out.println(isEven.computeTest(5));
// Output: true
System.out.println(isNegative.computeTest(-5));
}
interface MyGreeting {
String processName(String str);
}
public static void main(String args[]) {
MyGreeting morningGreeting = (str) -> "Good Morning " + str + "!";
MyGreeting eveningGreeting = (str) -> "Good Evening " + str + "!";
// Output: Good Morning Luis!
System.out.println(morningGreeting.processName("Luis"));
// Output: Good Evening Jessica!
System.out.println(eveningGreeting.processName("Jessica"));
}
上面示例中的变量morningGreeting
and eveningGreeting
,第 6 行和第 7 行,引用了MyGreeting
interface 并定义了不同的问候语。
在编写 lambda 表达式时,还可以像这样在表达式中显式指定参数的类型:
MyGreeting morningGreeting = (String str) -> "Good Morning " + str + "!";
MyGreeting eveningGreeting = (String str) -> "Good Evening " + str + "!";
块 lambda 表达式
到目前为止,我已经介绍了单表达式 lambda 的示例。当箭头运算符右侧的代码包含多个称为 的语句时,使用另一种类型的表达式block lambdas
:
interface MyString {
String myStringFunction(String str);
}
public static void main (String args[]) {
MyString reverseStr = (str) -> {
String result = "";
for(int i = str.length()-1; i >= 0; i--)
result += str.charAt(i);
return result;
};
// Output: omeD adbmaL
System.out.println(reverseStr.myStringFunction("Lambda Demo"));
}
通用功能接口
lambda 表达式不能是泛型的。但是与 lambda 表达式关联的函数式接口可以。可以编写一个通用接口并处理不同的返回类型,如下所示:
interface MyGeneric<T> {
T compute(T t);
}
public static void main(String args[]){
MyGeneric<String> reverse = (str) -> {
String result = "";
for(int i = str.length()-1; i >= 0; i--)
result += str.charAt(i);
return result;
};
MyGeneric<Integer> factorial = (Integer n) -> {
int result = 1;
for(int i=1; i <= n; i++)
result = i * result;
return result;
};
// Output: omeD adbmaL
System.out.println(reverse.compute("Lambda Demo"));
// Output: 120
System.out.println(factorial.compute(5));
}
Lambda 表达式作为参数
lambda 的一种常见用途是将它们作为参数传递。
它们可以用在任何提供目标类型的代码中。我觉得这很令人兴奋,因为它让我可以将可执行代码作为参数传递给方法。
要将 lambda 表达式作为参数传递,只需确保函数式接口类型与所需参数兼容。
interface MyString {
String myStringFunction(String str);
}
public static String reverseStr(MyString reverse, String str){
return reverse.myStringFunction(str);
}
public static void main (String args[]) {
MyString reverse = (str) -> {
String result = "";
for(int i = str.length()-1; i >= 0; i--)
result += str.charAt(i);
return result;
};
// Output: omeD adbmaL
System.out.println(reverseStr(reverse, "Lambda Demo"));
}