一、什么是 Lambda 表达式?
Lambda 表达式(也叫匿名函数)是 Java 8 引入的新特性,它让我们能够更简洁地表示接口中的单个方法(函数式接口),目的是让代码更简短、清晰,特别适合用在集合、并发等场景中。
总结: Lambda 是一种更短、更直观地写函数式接口实现的方法。
二、Lambda 表达式基本语法
(parameters) -> expression
或
(parameters) -> { statements }
parameters
:参数列表(可以省略类型,有一个参数时括号也可以省略)->
:箭头符号,读作“去”expression
或{ statements }
:方法体,可以是单行表达式或多行代码块
三、使用 Lambda 的前提
必须是“函数式接口”
函数式接口 = 只包含一个抽象方法的接口
例如:
Runnable
Comparator
Callable
- 自定义的单方法接口
(注:可以加上 @FunctionalInterface
注解,编译器强制检查)
四、示例
1:Runnable 的 Lambda 写法
传统写法:
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello World (传统写法)");
}
};
new Thread(runnable).start();
使用 Lambda:
Runnable runnable = () -> System.out.println("Hello World (Lambda 写法)");
new Thread(runnable).start();
简化了匿名内部类。
2:List 遍历(forEach)
传统写法:
List<String> list = Arrays.asList("Apple", "Banana", "Orange");
for (String item : list) {
System.out.println(item);
}
使用 Lambda:
List<String> list = Arrays.asList("Apple", "Banana", "Orange");
// 使用Lambda表达式 + forEach
list.forEach(item -> System.out.println(item));
代码量减少,可读性更好。
3:自定义 Comparator 排序
传统写法:
List<String> list = Arrays.asList("aaa", "b", "cc");
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
});
使用 Lambda:
List<String> list = Arrays.asList("aaa", "b", "cc");
// 使用Lambda表达式排序:按照字符串长度升序
Collections.sort(list, (s1, s2) -> s1.length() - s2.length());
Comparator 更加一目了然。
4:自定义函数式接口
定义一个函数式接口:
@FunctionalInterface // 表明这是一个函数式接口
interface Calculator {
int calculate(int a, int b);
}
使用 Lambda 表达式实现:
public class LambdaDemo {
public static void main(String[] args) {
// 使用Lambda表达式定义加法
Calculator add = (a, b) -> a + b;
// 使用Lambda表达式定义乘法
Calculator multiply = (a, b) -> a * b;
System.out.println("5 + 3 = " + add.calculate(5, 3));
System.out.println("5 * 3 = " + multiply.calculate(5, 3));
}
}
灵活实现不同业务逻辑。
5:Stream 流式处理
配合 Lambda,Stream 很强大!
List<String> list = Arrays.asList("Tom", "Jerry", "Spike", "Tyke");
// 过滤出名字长度大于3的,转成大写并打印
list.stream()
.filter(name -> name.length() > 3) // 过滤
.map(name -> name.toUpperCase()) // 转换
.forEach(name -> System.out.println(name)); // 遍历打印
链式调用,代码清爽高效。
五、Lambda 表达式的简化规则
- 参数类型可以省略(编译器能推断)
- 只有一个参数时,括号可以省略
- 只有一行代码时,大括号
{}
和return
可以省略
// 完整写法
list.forEach((String item) -> { System.out.println(item); });
// 省略参数类型
list.forEach((item) -> { System.out.println(item); });
// 一个参数可以省略括号
list.forEach(item -> { System.out.println(item); });
// 一行代码可以省略大括号
list.forEach(item -> System.out.println(item));
六、常见 Lambda 写法对照表
场景 | 传统匿名内部类写法 | Lambda表达式写法 | 说明 |
---|---|---|---|
Runnable | new Runnable() { public void run() { System.out.println("Hello"); } } | () -> System.out.println("Hello") | 无参数,无返回值 |
Callable | new Callable<String>() { public String call() { return "Done"; } } | () -> "Done" | 无参数,有返回值 |
Comparator | new Comparator<String>() { public int compare(String a, String b) { return a.length() - b.length(); } } | (a, b) -> a.length() - b.length() | 有参数,有返回值 |
Listener(如按钮点击) | new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("Clicked"); } } | e -> System.out.println("Clicked") | 一个参数,单行处理 |
Consumer(消费型接口) | new Consumer<String>() { public void accept(String s) { System.out.println(s); } } | s -> System.out.println(s) | 处理一个输入,无返回 |
Supplier(供给型接口) | new Supplier<String>() { public String get() { return "Hello"; } } | () -> "Hello" | 无参数,提供一个返回值 |
Function(函数型接口) | new Function<Integer, String>() { public String apply(Integer i) { return String.valueOf(i); } } | i -> String.valueOf(i) | 输入一个,输出一个 |
Predicate(断言型接口) | new Predicate<String>() { public boolean test(String s) { return s.isEmpty(); } } | s -> s.isEmpty() | 输入一个,返回boolean |
七、总结
特性 | 说明 |
---|---|
适用接口 | 只能用在函数式接口上(一个抽象方法) |
简化写法 | 可以省略参数类型、小括号、大括号、return |
搭配 Stream | 更强大,如 map、filter、reduce 等 |
可读性 | 简单场景提升,可读性好;复杂逻辑要谨慎 |
经典应用场景 | 集合操作、线程处理、事件监听、回调函数等 |