无需if-else实现多流程按序取值空值回退的可扩展方案
最优实现方案
针对你提到的两个痛点,直接利用JDK原生Optional的短路特性+流程列表化改造即可,完全不需要引入额外依赖,同时满足两个核心要求:
- 高优先级流程拿到值后,后续低优先级流程完全不会执行,无多余性能损耗
- 新增/调整取值流程优先级只需要修改流程列表,不需要重复编写if空判断分支
核心实现逻辑
核心利用Optional.or(Supplier<? extends Optional<? extends T>> supplier)方法的原生短路特性:当Optional实例本身持有非空值时,直接返回当前实例,完全不会执行传入的Supplier逻辑;只有当实例为空时,才会调用Supplier尝试获取下一个值。
代码实现
首先把所有取值流程按优先级从高到低封装为Supplier列表,后续新增流程只需要往列表里追加即可:
// 按优先级排序的取值流程列表,新增流程直接按顺序添加 List<Supplier<Optional<TargetValue>>> fetchProcesses = List.of( () -> fetchFromProcessA(), // 最高优先级:流程A () -> fetchFromProcessB(), // 次优先级:流程B () -> fetchFromProcessC() // 后续新增流程直接往下追加 ); // 初始化为空值,依次尝试所有流程 Optional<TargetValue> valueHolder = Optional.empty(); for (Supplier<Optional<TargetValue>> process : fetchProcesses) { valueHolder = valueHolder.or(process); // 拿到值直接终止遍历,连后续流程的判断都省掉 if (valueHolder.isPresent()) { break; } } // 所有流程都没拿到值就抛出指定异常 TargetValue finalValue = valueHolder.orElseThrow(() -> new IllegalStateException("所有取值流程执行完成,未获取到有效结果") );
单个取值流程的写法要求
每个独立的取值方法只需要关注自身逻辑,取值成功就返回包好值的Optional,取值失败/执行异常就返回空Optional即可,不需要关心其他流程的逻辑:
private Optional<TargetValue> fetchFromProcessA() { try { // 这里写流程A的具体取值逻辑,比如查本地缓存、读默认配置等 TargetValue result = doFetchA(); return Optional.ofNullable(result); } catch (Exception e) { // 流程执行异常视为取值失败,返回空即可自动走下一个流程 return Optional.empty(); } }
常见误区提醒
不要直接用Stream的map方法串联所有Supplier,这种写法会提前执行所有取值流程,失去短路特性:
// 错误写法:会执行所有流程的取值逻辑,哪怕流程A已经拿到值 TargetValue wrongDemo = Stream.of( () -> fetchFromProcessA(), () -> fetchFromProcessB() ) .map(Supplier::get) // 这里会把所有Supplier都执行一遍 .filter(Optional::isPresent) .findFirst() .orElseThrow();
如果一定要用流式写法,可以自定义懒加载的流处理逻辑,但从可读性和执行效率来看,前面的循环写法是最优选择。
内容的提问来源于stack exchange,提问作者Bramanta
相关产品推荐
相关产品推荐

