理解 Lambda 表达式的基本概念及其在 Java 中的作用
掌握 Lambda 表达式的语法结构与参数类型
学会将 Lambda 表达式应用于函数式接口、集合和流操作
了解常用内置函数式接口(如 Predicate、Consumer 等)的用途
能够判断 Lambda 表达式的合法性并避免常见错误
Lambda 表达式是 Java 8 引入的一项重要特性,它允许开发者以简洁的方式编写函数式风格的代码。本质上,Lambda 表达式是一种匿名函数,可以像数据一样被传递或赋值给变量,从而显著提升代码的可读性和简洁性。
Lambda 表达式必须实现一个函数式接口——即只包含一个抽象方法的接口。通过 Lambda,我们可以直接提供该抽象方法的实现,而无需显式定义类或匿名内部类。
基本示例
interface Add {
int addition(int a, int b);
}
public class Main {
public static void main(String[] args) {
// 使用 Lambda 表达式实现加法
Add add = (a, b) -> a + b;
int result = add.addition(10, 20);
System.out.println("Sum: " + result);
}
}输出:
Sum: 30Lambda 表达式由三部分组成:
参数列表:方法所需的输入参数
箭头符号(->):分隔参数与主体
主体:要执行的逻辑,可以是单个表达式或代码块
通用语法如下:
(parameters) -> expression
或
(parameters) -> { statements; }函数式接口是指仅包含一个抽象方法的接口。Java 提供了 @FunctionalInterface 注解用于显式声明此类接口(虽非强制,但强烈推荐),以便在编译期检查是否符合规范。
@FunctionalInterface
interface FuncInterface {
void abstractFun(int x);
// 默认方法不影响“函数式”性质
default void normalFun() {
System.out.println("Hello");
}
}
public class Main {
public static void main(String[] args) {
FuncInterface fobj = (int x) -> System.out.println(2 * x);
fobj.abstractFun(5); // 输出:10
}
}根据参数数量不同,Lambda 表达式可分为以下三类:
@FunctionalInterface
interface ZeroParameter {
void display();
}
public class Main {
public static void main(String[] args) {
ZeroParameter lambda = () ->
System.out.println("This is a zero-parameter lambda expression!");
lambda.display();
}
}输出:
This is a zero-parameter lambda expression!语法:
() -> 表达式
当只有一个参数且类型可推断时,括号可省略。
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
System.out.println("All elements:");
list.forEach(n -> System.out.println(n));
System.out.println("Even elements:");
list.forEach(n -> {
if (n % 2 == 0)
System.out.println(n);
});
}
}输出:
All elements:
1
2
3
Even elements:
2注意:
forEach()内部使用的是Consumer<T>函数式接口,接受一个参数并执行操作,无返回值。
@FunctionalInterface
interface Functional {
int operation(int a, int b);
}
public class Main {
public static void main(String[] args) {
Functional add = (a, b) -> a + b;
Functional multiply = (a, b) -> a * b;
System.out.println(add.operation(6, 3)); // 9
System.out.println(multiply.operation(4, 5)); // 20
}
}语法:
(p1, p2, ...) -> 表达式
Lambda 表达式极大简化了对集合的操作,尤其在配合 Stream API 时表现突出。
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Adam");
System.out.println("All names:");
names.forEach(name -> System.out.println(name));
System.out.println("\nNames starting with 'A':");
names.stream()
.filter(n -> n.startsWith("A")) // 过滤
.map(n -> n.toUpperCase()) // 转换
.forEach(System.out::println); // 输出
}
}输出:
All names:
Alice
Bob
Charlie
Adam
Names starting with 'A':
ALICE
ADAM此处:
filter使用Predicate<String>
map使用Function<String, String>
forEach使用Consumer<String>
代码更简洁:相比匿名内部类,大幅减少样板代码
支持函数式编程:将行为作为参数传递,提升抽象能力
提高可读性:逻辑集中,意图清晰
增强集合处理能力:与 Stream API 结合,轻松实现过滤、映射、归约等操作
注意:
Comparable是普通接口,但常与 Lambda 配合使用(如Collections.sort(list, (a, b) -> a.compareTo(b)))。
Lambda 表达式是 Java 实现函数式编程的核心工具
必须与函数式接口配合使用(仅含一个抽象方法)
支持零参、单参、多参形式,参数类型通常可自动推断
广泛应用于集合遍历、Stream 流处理、事件回调等场景
内置函数式接口(如 Predicate、Consumer)极大提升了开发效率
编写时需注意语法细节,尤其是类型推断和语句完整性
为什么 Lambda 表达式不能用于包含多个抽象方法的接口?请结合函数式接口的定义说明。
在以下代码中,能否将 (n) -> System.out.println(n) 简化为 n -> System.out.println(n)?为什么?
list.forEach((n) -> System.out.println(n));尝试使用 Lambda 表达式和 Stream API 实现:从一个整数列表中筛选出大于 10 的偶数,并将其平方后求和。