330. Java Stream API - 处理 Optional 对象:像流一样优雅地使用 Optional
💡 为什么 Optional 也有 map、filter 和 flatMap?
Optional<T> 并不仅仅是"可能有值"的盒子,它也支持一套轻量的函数式 API,让我们像处理 Stream 一样优雅地处理单个值。
与 Stream API 一样,Optional 也有:
map(Function<T, R>)filter(Predicate<T>)flatMap(Function<T, Optional<R>>)(注意:不是返回Stream)
🎯 这让
Optional与Stream的处理流程无缝衔接,代码更简洁、流畅、可读性更强!
✅ 方法行为说明
Optional 状态 |
调用 map/filter/flatMap 的行为 |
|---|---|
| 是空的 | 返回空 Optional(不执行函数) |
| 非空值 | 执行函数并返回新 Optional |
📘 示例:查找指定 ID 的客户名称
java
record Customer(int id, String name) {}
List<Customer> customers = List.of(
new Customer(1, "Mary"),
new Customer(2, "James"),
new Customer(3, "Patricia"),
new Customer(4, "Michael")
);
int id = 2;
String name = customers.stream()
.filter(customer -> customer.id() == id) // 找到 ID 匹配的 Customer
.findFirst() // 返回 Optional<Customer>
.map(Customer::name) // 提取名字 -> Optional<String>
.orElse("UNKNOWN"); // 若无匹配,返回默认值
System.out.println("Name of customer with id " + id + ": " + name);
💬 输出结果:
java
Name of customer with id 2: James
🧠 逐步解析逻辑:
java
.findFirst()
返回的是 Optional<Customer>,可能为空。
java
.map(Customer::name)
如果 Optional 中有值,就提取出 name 字段;否则保留为空。
java
.orElse("UNKNOWN")
如果没有任何匹配,就返回默认值 "UNKNOWN"。
✅ 你无需显式判断
Optional是否为空,因为map/orElse等操作已内建处理逻辑!
🎯 与传统代码对比
传统做法(繁琐):
java
Customer match = null;
for (Customer c : customers) {
if (c.id() == id) {
match = c;
break;
}
}
String name = (match != null) ? match.name() : "UNKNOWN";
使用 Stream + Optional 的方式(简洁、表达力强):
java
String name = customers.stream()
.filter(c -> c.id() == id)
.findFirst()
.map(Customer::name)
.orElse("UNKNOWN");
更易读,也不容易出错。
🧪 更多操作举例
1. 使用 filter() 精准筛选:
java
Optional<String> name = Optional.of("Alice");
name.filter(n -> n.length() > 3)
.ifPresent(System.out::println); // 输出:Alice
若不满足条件,则返回 Optional.empty(),后续操作自动跳过。
2. 使用 flatMap() 链接多个 Optional:
java
Optional<String> emailOpt = Optional.of("user@example.com");
Optional<String> domainOpt = emailOpt.flatMap(email -> {
int atIndex = email.indexOf("@");
return (atIndex >= 0) ? Optional.of(email.substring(atIndex + 1))
: Optional.empty();
});
domainOpt.ifPresent(System.out::println); // 输出:example.com
与 map() 不同,flatMap() 要求函数返回的就是一个 Optional,避免嵌套 Optional<Optional>。
🧭 总结:像流水线一样优雅处理 Optional
| 操作方法 | 作用 | 返回类型 |
|---|---|---|
map() |
映射值为其他类型 | Optional |
filter() |
按条件保留值,否则为空 | Optional |
flatMap() |
映射并展开成另一个 Optional | Optional |
orElse() |
提供默认值 | T |
orElseThrow() |
缺值时报异常 | T 或 Exception |
🧠 最佳实践提示
Optional可配合 Stream 使用,构建极其简洁的处理流程- 善用
map()、filter()、flatMap(),避免冗余判断逻辑 - 所有操作都可链式组合,思路更清晰,也更容易测试