Java Lambda 表达式 是 Java 8 引入的最强大语法之一,可以让代码更简洁、高效。下面整理出一份 「Java Lambda 表达式大全」 ------ 从语法基础到实际业务应用,附带示例与最佳实践。
🧩 一、Lambda 表达式基础语法
✅ 语法结构:
plain
(参数列表) -> { 方法体 }
可简化形式:
| 写法 | 示例 | 说明 |
|---|---|---|
| 1. 无参数,无返回值 | () -> System.out.println("Hello") |
Runnable 风格 |
| 2. 一个参数,无返回值 | x -> System.out.println(x) |
可省略括号 |
| 3. 多个参数,有返回值 | (a, b) -> a + b |
自动推断类型 |
| 4. 有多条语句 | (x, y) -> { int sum = x + y; return sum; } |
需要 {} 和 return |
💡 二、常用函数式接口(java.util.function)
| 接口 | 方法 | 作用行动 | 示例 |
|---|---|---|---|
Predicate<T> |
boolean test(T t) |
判断条件 | str -> str.isEmpty() |
Function<T,R> |
R apply(T t) |
转换类型 | str -> str.length() |
Consumer<T> |
void accept(T t) |
消费数据(无返回) | s -> System.out.println(s) |
Supplier<T> |
T get() |
生成数据 | () -> new Date() |
UnaryOperator<T> |
T apply(T t) |
一元操作 | x -> x * x |
BinaryOperator<T> |
T apply(T t1, T t2) |
二元操作 | (a, b) -> a + b |
Comparator<T> |
int compare(T o1, T o2) |
比较大小 | (a, b) -> a.getAge() - b.getAge() |
🧰 三、集合操作(最常用场景)
1️⃣ 遍历
plain
list.forEach(item -> System.out.println(item));
等价于:
plain
for (String item : list) System.out.println(item);
2️⃣ 过滤(filter)2️⃣过滤(过滤器)
plain
List<String> filtered = list.stream()
.filter(s -> s.startsWith("A"))
.toList();
3️⃣ 转换(map)
plain
List<Integer> lengths = list.stream()
.map(String::length)
.toList();
4️⃣ 排序(sorted)4️⃣排序(已排序)
plain
list.stream()
.sorted((a, b) -> a.compareToIgnoreCase(b))
.forEach(System.out::println);
5️⃣ 去重(distinct)5️⃣去重(不同)
plain
list.stream()
.distinct()
.toList();
6️⃣ 统计 / 汇总(reduce)
plain
int sum = list.stream()
.mapToInt(Integer::intValue)
.reduce(0, Integer::sum);
7️⃣ 删除(removeIf)
plain
list.removeIf(item -> item == null || item.isEmpty());
8️⃣ 条件判断(anyMatch / allMatch / noneMatch)
plain
boolean hasAdmin = users.stream()
.anyMatch(u -> u.getRole().equals("ADMIN"));
⚙️ 四、实际业务示例
🧾 1. 清理无效ID
plain
unread.removeIf(id -> !allUsers.contains(id));
🧠 2. 计算所有工人的平均工资
plain
double avg = employees.stream()
.mapToDouble(Employee::getSalary)
.average()
.orElse(0.0);
📦 3. 提取对象属性并拼接成字符串
plain
String names = users.stream()
.map(User::getName)
.collect(Collectors.joining(", "));
📊 4. 分组统计
plain
Map<String, Long> group = users.stream()
.collect(Collectors.groupingBy(User::getRole, Collectors.counting()));
🧠 五、结合 Optional 的 Lambda
plain
Optional.ofNullable(user)
.map(User::getEmail)
.ifPresent(email -> System.out.println("邮箱:" + email));
💬 六、方法引用(Lambda 的简化写法)
| 写法 | 等价于 |
|---|---|
System.out::println |
x -> System.out.println(x) |
String::toUpperCase |
s -> s.toUpperCase() |
User::getName |
u -> u.getName() |
User::new |
() -> new User() |
🧭 七、Lambda 常见坑点
| 坑点 | 说明 |
|---|---|
| Lambda 不能抛受检异常 | 必须 try-catch 或自定义包装函数 |
| 不建议在循环中频繁创建 Stream | Stream 是惰性计算,推荐链式使用 |
| 修改外部变量需谨慎 | Lambda 内部不能修改非 final 局部变量 |
| 不要滥用 Lambda | 逻辑复杂时反而影响可读性 |
✨ 八、总结口诀
✅ Lambda 三要素口诀:
参数(输入) → 操作(逻辑) → 输出(结果)用
->连接,用 Stream 串联!