Appearance
Lambda 表达式
为什么需要 Lambda?
Lambda 是 Java 8 引入的函数式编程特性,让代码更简洁。
┌─────────────────────────────────────────────────────────────────┐
│ Lambda 解决的问题 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ❌ 传统写法(匿名内部类) │
│ ───────────────────── │
│ new Thread(new Runnable() { │
│ @Override │
│ public void run() { │
│ System.out.println("Hello"); │
│ } │
│ }).start(); │
│ │
│ ✅ Lambda 写法 │
│ ───────────────────── │
│ new Thread(() -> System.out.println("Hello")).start(); │
│ │
└─────────────────────────────────────────────────────────────────┘Lambda 语法
基本语法
java
// 完整语法
(参数列表) -> { 方法体 }
// 示例
(int a, int b) -> { return a + b; }
// 简化规则:
// 1. 参数类型可省略
(a, b) -> { return a + b; }
// 2. 单参数括号可省略
name -> System.out.println(name);
// 3. 单行方法体 return 可省略
(a, b) -> a + b
// 4. 单参数类型可省略
String s -> s.length()示例对比
java
// 完整语法
BiFunction<Integer, Integer, Integer> add = (Integer a, Integer b) -> {
return a + b;
};
// 省略参数类型
BiFunction<Integer, Integer, Integer> add2 = (a, b) -> {
return a + b;
};
// 单行省略 return
BiFunction<Integer, Integer, Integer> add3 = (a, b) -> a + b;
// 单参数省略括号
Function<String, Integer> len = s -> s.length();函数式接口
什么是函数式接口?
只有一个抽象方法的接口,可以用 Lambda 表达式简化。
java
// 函数式接口标记
@FunctionalInterface
public interface MyFunction {
int apply(int a, int b);
}
// 使用
MyFunction func = (a, b) -> a + b;
System.out.println(func.apply(1, 2)); // 3常用函数式接口
| 接口 | 方法 | 说明 | 示例 |
|---|---|---|---|
Supplier<T> | T get() | 生产者 | () -> "hello" |
Consumer<T> | void accept(T t) | 消费者 | s -> System.out.println(s) |
Function<T,R> | R apply(T t) | 转换 | s -> s.length() |
Predicate<T> | boolean test(T t) | 断言 | s -> s.isEmpty() |
UnaryOperator<T> | T apply(T t) | 一元运算 | x -> x * 2 |
BinaryOperator<T> | T apply(T t1, T t2) | 二元运算 | (a, b) -> a + b |
常用接口示例
java
// Supplier - 生产数据
Supplier<String> supplier = () -> "Hello";
String result = supplier.get(); // "Hello"
// Consumer - 消费数据
Consumer<String> consumer = s -> System.out.println(s);
consumer.accept("Hello"); // 打印 Hello
// Function - 转换数据
Function<String, Integer> function = s -> s.length();
int len = function.apply("Hello"); // 5
// Predicate - 判断
Predicate<String> predicate = s -> s.length() > 3;
boolean test = predicate.test("Hello"); // true
// 组合使用
Function<String, Integer> f = s -> s.length();
Predicate<Integer> p = len -> len > 3;
boolean result = p.test(f.apply("Hello")); // true方法引用
四种形式
java
// 1. 静态方法引用 ClassName::staticMethod
Function<Integer, String> toBinary = Integer::toBinaryString;
System.out.println(toBinary.apply(10)); // "1010"
// 2. 实例方法引用 instance::method
String str = "Hello";
Supplier<Integer> len = str::length;
System.out.println(len.get()); // 5
// 3. 任意实例方法引用 ClassName::method
Function<String, Integer> length = String::length;
System.out.println(length.apply("World")); // 5
// 4. 构造方法引用 ClassName::new
Supplier<Person> personSupplier = Person::new;
Person person = personSupplier.get();
Function<String, Person> personFunction = Person::new;
Person p = personFunction.apply("张三", 25);方法引用 vs Lambda
java
// Lambda
s -> s.toUpperCase()
// 方法引用(更简洁)
String::toUpperCase
// 比较
list.sort((s1, s2) -> s1.compareTo(s2));
list.sort(String::compareTo); // 等价闭包与变量作用域
访问外部变量
java
// Lambda 可以访问外部变量( effectively final)
int base = 10;
Function<Integer, Integer> add = x -> x + base;
System.out.println(add.apply(5)); // 15
// base = 20; // 编译错误!base 被隐式 finalthis 引用
java
public class ThisDemo {
private String name = "Outer";
public void test() {
// Lambda 中的 this 是包围类的 this
Runnable r = () -> System.out.println(this.name);
r.run(); // 打印 "Outer"
}
}实战应用
集合操作
java
List<String> names = Arrays.asList("Tom", "Jerry", "Mike", "John");
// forEach
names.forEach(name -> System.out.println(name));
// filter + collect
List<String> filtered = names.stream()
.filter(name -> name.length() > 3)
.collect(Collectors.toList());
// map 转换
List<Integer> lengths = names.stream()
.map(name -> name.length())
.collect(Collectors.toList());
// sort
names.sort((a, b) -> b.compareTo(a));
names.sort(Comparator.reverseOrder());策略模式
java
// 传统策略模式
interface PaymentStrategy {
void pay(double amount);
}
class PayByAlipay implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("支付宝支付:" + amount);
}
}
// 使用 Lambda(无需创建策略类)
public void pay(double amount, Consumer<Double> paymentMethod) {
paymentMethod.accept(amount);
}
// 调用
pay(100.0, money -> System.out.println("支付宝支付:" + money));
pay(100.0, money -> System.out.println("微信支付:" + money));总结
Lambda 核心知识点:
| 知识点 | 说明 |
|---|---|
| 语法 | (params) -> expression 或 (params) -> { statements } |
| 函数式接口 | 只有一个抽象方法的接口 |
| 方法引用 | ClassName::method 或 instance::method |
| 变量捕获 | 只能访问 effectively final 变量 |
⚠️ 易错点提醒:
- Lambda 表达式外部变量必须是 final 或 effectively final
- Lambda 不能访问接口的默认方法
- 方法引用
String::length等价于s -> s.length() - 构造方法引用
ClassName::new