orElseGet() 延迟执行 Supplier,避免空 Optional 时的无谓开销;orElse() 立即求值参数,即使 Optional 非空也会构造默认对象,导致数据库查询等高成本操作被冗余执行。
当 optional 为空时,orelseget() 会执行传入的 supplier,而 lambda 表达式正是最自然的 supplier 实现方式——它让高开销的默认值只在真正需要时才创建,避免无谓的资源浪费。
为什么不用 orElse()?
orElse(T other) 的参数是**立即求值**的:无论 Optional 是否为空,other 都会在调用前被构造。例如:
// 即使 userOptional 有值,new ExpensiveObject() 仍会被执行User user = userOptional.orElse(new ExpensiveObject());
若 ExpensiveObject 初始化涉及数据库查询、文件读取或复杂计算,这会造成显著性能损耗。
用 orElseGet() + lambda 延迟执行
orElseGet(Supplier extends T> supplier) 接收一个 Supplier,仅在 Optional 为空时才调用其 get() 方法。lambda 让语法简洁且语义清晰:
- 写法直接:
orElseGet(() -> new ExpensiveObject()) - 逻辑明确:只有“缺省值”真正被用到时,才触发初始化
- 支持带逻辑的默认值,比如根据上下文动态生成
// ✅ 正确:仅当 optional 为空时才创建Connection conn = connectionOptional.orElseGet(() -> createNewConnection());
更灵活的 lambda 使用场景
lambda 不限于简单构造,可封装条件判断、日志记录或 fallback 策略:
- 结合缓存重试:
orElseGet(() -> cache.computeIfAbsent("key", k -> fetchFromRemote())) - 记录缺失事件:
orElseGet(() -> { log.warn("Config missing, using defaults"); return DefaultConfig.INSTANCE; }) - 多级 fallback:
orElseGet(() -> secondarySource.get().orElseGet(() -> new FallbackValue()))
注意事项
确保 lambda 体中不抛出受检异常(除非包装为 RuntimeException),因为 Supplier#get() 不声明 throws;若需处理 I/O 异常,建议提前捕获并转换:
orElseGet(() -> {<br>
try { return loadFromFile(); }<br>
catch (IOException e) { throw new UncheckedIOException(e); }<br>
})
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











