Lambda 表达式
- 1. 概况
- 2. 函数式接口
- 3. 格式
- 3.1 完整格式
- 3.2 省略格式
- 4. 代码示例
- 5. 输出结果
- 6. 注意事项
学习Lambda表达式之前最好先学会 匿名内部类
具体信息请查看 API 帮助文档
1. 概况
Lambda 表达式是一种在编程中用来表示匿名函数的简洁语法。它是基于函数式编程风格的一种特性,最初在Java 8中引入。Lambda 表达式允许开发者将函数作为方法参数传递或者以内联的方式定义,并且可以使用函数式接口进行类型推断。
Lambda 表达式的语法可以分为三个部分:
- 形参列表:指定函数的输入参数,可以有零个或多个参数。
- 箭头符号(
->
):分隔参数列表和Lambda表达式的主体。 - Lambda表达式主体:定义了函数的逻辑。
Lambda 表达式与匿名内部类类似,但它更加简洁、灵活,并且可读性更强。使用Lambda表达式可以更加方便地编写函数式接口的实现,减少代码量,并提高代码的可读性。
2. 函数式接口
函数式接口是指仅包含一个抽象方法的接口。函数式接口在函数式编程中以被Lambda表达式所使用。Java 8及以上版本引入了对函数式接口的支持。
函数式接口的特点:
-
只包含一个抽象方法
函数式接口只有一个未实现的方法,该方法即为函数式接口的抽象方法。其余的方法可以是默认方法或静态方法,不影响函数式接口的特性。
-
能够使用Lambda表达式
由于函数式接口只有一个抽象方法,所以可以使用Lambda表达式来实现该方法。
-
可以使用注解
@FunctionalInterface
显式标记使用该注解可以确保接口是一个函数式接口,如果接口不符合函数式接口的定义(包含多个抽象方法),编译器会报错。
函数式接口可以用于各种场景,包括但不限于:
-
函数作为参数:函数式接口可以作为方法参数,通过Lambda表达式传递函数的逻辑。
-
Lambda表达式和方法引用:函数式接口可以通过Lambda表达式或者方法引用进行实例化。
-
并发编程:函数式接口常用于并发编程中的函数式接口API(如
java.util.function
包),以提供便捷的线程操作。
Java 8提供了一些常用的函数式接口,例如
Function
、Predicate
、Consumer
、Supplier
等,它们可以通过java.util.function
包进行使用。
3. 格式
3.1 完整格式
- 完整格式
Lambda表达式:
格式:
() -> {
方法体 ;
}
-
() :对应着方法的形参
-
-> :固定格式
-
{} :对应着方法的方法体
例如:
// Lambda表达式完整形式按照字符串的长度升序排序
Arrays.sort(arr, (String o1, String o2) -> {
return o1.length() - o2.length();
}
);
3.2 省略格式
-
Lambda的省略规则:
-
1.参数类型可以省略不写
-
2.如果只有一个参数,参数类型可以省略,同时()可以省略
-
3.如果Lambda表达式的方法体只有一行,大括号,分号,return可以省略不写,需要同时省略
-
例如:
//Lambda表达式省略形式按照字符串的长度升序排序
Arrays.sort(arr, (o1, o2) -> o1.length() - o2.length());
4. 代码示例
需求:利用Lambda表达式对下列数据进行排序,数据如下 {3, 8, 5, 9, 4, 10, 3, 3, 5, 6};
例如:
package text.text02;
import java.util.Arrays;
import java.util.Comparator;
/*
Lambda表达式:
格式:
() -> {
方法体 ;
}
():对应着方法的形参
->:固定格式
{}:对应着方法的方法体
注意点:
Lambda表达式可以用来简化匿名内部类的代码
Lambda表达式只能简化函数式接口的匿名内部类的写法
函数式接口:有且仅有一个抽象方法的接口叫做函数式接口,接口上面可以加上@FunctionalInterface注解
Lambda的省略规则:
1.参数类型可以省略不写
2.如果只有一个参数,参数类型可以省略,同时()可以省略
3.如果Lambda表达式的方法体只有一行,大括号,分号,return可以省略不写,需要同时省略
*/
public class text17 {
public static void main(String[] args) {
Integer[] arr = {3, 8, 5, 9, 4, 10, 3, 3, 5, 6};
//匿名内部类
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
System.out.println("升序匿名内部类:" + Arrays.toString(arr)); //升序匿名内部类:[3, 3, 3, 4, 5, 5, 6, 8, 9, 10]
//Lambda表达式完整写法
Arrays.sort(arr,
(Integer o1, Integer o2) -> {
return o2 - o1;
}
);
System.out.println("降序Lambda表达式完整写法:" + Arrays.toString(arr)); //降序Lambda表达式完整写法:[10, 9, 8, 6, 5, 5, 4, 3, 3, 3]
// Lambda表达式省略写法
Arrays.sort(arr, (o1, o2) -> o2 - o1);
System.out.println("降序Lambda表达式省略写法:" + Arrays.toString(arr)); //降序Lambda表达式省略写法:[10, 9, 8, 6, 5, 5, 4, 3, 3, 3]
}
}
5. 输出结果
6. 注意事项
在使用Lambda表达式时的注意事项:
-
函数式接口匹配:Lambda表达式通常用于函数式接口的实现。确保Lambda表达式的参数列表和返回类型与函数式接口的抽象方法匹配。
-
变量捕获:Lambda表达式可以捕获外部的局部变量,但需要注意这些变量必须是最终(final)或实际上是最终(effectively final)的。这是因为Lambda表达式创建的闭包会持有对这些变量的引用。
-
方法引用:Lambda表达式可以通过方法引用来简化代码。方法引用是对已有方法的引用,可以通过
ClassName::methodName
的方式来表示。 -
括号的使用:当Lambda表达式的主体只有一条语句时,可以省略大括号。但是,如果这条语句是一个代码块,需要使用大括号将代码块括起来。
-
异常处理:Lambda表达式中的异常需要显示地处理或声明。可以使用try-catch语句处理异常,也可以在函数式接口的方法声明中使用throws子句声明异常。