Java Lambda 表达式详解:从入门到实战
1. Lambda 表达式基础
Lambda 表达式是 Java 8 引入的函数式编程核心特性,本质是匿名函数。其语法结构为:
(参数列表) -> { 函数体 }- 单参数简化:当参数只有一个时可省略括号
x -> x * x - 单行简化:当函数体仅一行时可省略大括号
(a, b) -> a + b - 类型推断:编译器自动推导参数类型
(s) -> s.length()等价于(String s) -> s.length()
2. 函数式接口:Lambda 的基石
Lambda 必须与函数式接口配合使用,即仅含一个抽象方法的接口:
@FunctionalInterface interface Calculator { int compute(int a, int b); // 唯一抽象方法 }使用 Lambda 实现:
Calculator add = (x, y) -> x + y; System.out.println(add.compute(3, 5)); // 输出 8常见函数式接口:
Consumer<T>:消费型void accept(T t)Supplier<T>:供给型T get()Function<T,R>:转换型R apply(T t)Predicate<T>:断言型boolean test(T t)
3. 方法引用:Lambda 的语法糖
四种方法引用简化 Lambda:
| 类型 | 语法 | 等价 Lambda |
|---|---|---|
| 静态方法引用 | 类名::方法名 | (args) -> 类名.方法名(args) |
| 实例方法引用 | 对象::方法名 | (args) -> 对象.方法名(args) |
| 类实例方法引用 | 类名::方法名 | (obj, args) -> obj.方法名(args) |
| 构造器引用 | 类名::new | (args) -> new 类名(args) |
示例:
// 静态方法引用 Function<String, Integer> parser = Integer::parseInt; // 实例方法引用 List<String> list = Arrays.asList("A", "B"); list.forEach(System.out::println);4. 实战应用场景
场景 1:集合操作
List<Integer> numbers = Arrays.asList(1, 2, 3, 4); // 过滤偶数 List<Integer> evens = numbers.stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList()); // 平方映射 List<Integer> squares = numbers.stream() .map(x -> x * x) .collect(Collectors.toList());场景 2:多线程
// 传统方式 new Thread(new Runnable() { @Override public void run() { System.out.println("Thread running"); } }).start(); // Lambda 简化 new Thread(() -> System.out.println("Lambda thread")).start();场景 3:事件处理
JButton button = new JButton("Click"); button.addActionListener( event -> System.out.println("Button clicked") );5. Lambda 与闭包
Lambda 可捕获最终变量(final 或 effectively final):
int base = 10; // effectively final Function<Integer, Integer> adder = x -> x + base; System.out.println(adder.apply(5)); // 输出 156. 设计模式优化
策略模式简化:
// 传统接口实现 class AddStrategy implements Operation { public int execute(int a, int b) { return a + b; } } // Lambda 实现 Operation add = (a, b) -> a + b; Operation multiply = (a, b) -> a * b;7. 性能注意事项
- 优点:减少匿名类对象创建,提升代码简洁性
- 缺点:首次调用有初始化开销(类加载、链接)
- 建议:高频调用场景优先使用,避免复杂嵌套
8. 总结
Lambda 表达式通过行为参数化实现了函数式编程范式:
- 语法简洁:
(参数) -> 表达式 - 依赖函数式接口:
@FunctionalInterface - 与方法引用互补:
类名::方法名 - 核心价值:提升代码抽象层级,使集合操作、并发处理更简洁
终极示例:文件处理流水线
Files.lines(Paths.get("data.txt")) .filter(line -> !line.startsWith("#")) // 过滤注释 .map(String::toUpperCase) // 转为大写 .sorted(Comparator.reverseOrder()) // 倒序排序 .forEach(System.out::println); // 输出