Lambda 用「传代码」替换 if-else 全解

一、核心一句话(必背)

传统:if/else 写死分支逻辑;Lambda 行为参数化:把每个分支的业务代码当成参数传入通用方法,消灭成堆 if else,一套通用代码适配 N 种分支,本质就是策略模式语法简化。

痛点:分支越来越多→if 嵌套爆炸、改一处动全代码、违反开闭原则;Lambda:新增分支不用改原有代码,只传新 Lambda。

二、传统 if-else 反面示例(看出弊端)

场景:订单结算,不同优惠(满减 / 折扣 / 无优惠)

public BigDecimal calcPrice(BigDecimal originPrice,String type){
    if("FULL".equals(type)){
        //满100减20
        return originPrice.compareTo(BigDecimal.valueOf(100))>=0
                ? originPrice.subtract(BigDecimal.valueOf(20)):originPrice;
    }else if("DISCOUNT".equals(type)){
        //8折
        return originPrice.multiply(new BigDecimal("0.8"));
    }else if("NONE".equals(type)){
        return originPrice;
    }else {
        throw new RuntimeException("优惠类型不存在");
    }
}

缺点:

  1. 新增「优惠券抵扣」,必须改方法加 else if;
  2. 分支臃肿、可读性差、维护难、重复造轮子。

三、Lambda 改造思路三步走(固定套路)

步骤 1:函数式接口,封装分支执行代码(承载一段业务逻辑)

@FunctionalInterface
public interface DiscountFunc {
    BigDecimal calc(BigDecimal price);
}

接口 = 统一规范,每个优惠规则就是一个 Lambda 实现。

步骤 2:Map 预先绑定【类型标识→Lambda 代码】(替代 if 分支映射)

//全局静态Map,key:优惠类型,value:对应执行逻辑(Lambda代码)
private static final Map<String, DiscountFunc> DISCOUNT_MAP = new HashMap<>();

static {
    //满减
    DISCOUNT_MAP.put("FULL", p -> p.compareTo(BigDecimal.valueOf(100)) >= 0
            ? p.subtract(BigDecimal.valueOf(20)) : p);
    //8折
    DISCOUNT_MAP.put("DISCOUNT", p -> p.multiply(new BigDecimal("0.8")));
    //无优惠
    DISCOUNT_MAP.put("NONE", p -> p);
}

步骤 3:只写一个通用结算方法,去掉所有 if

public BigDecimal calcPrice(BigDecimal originPrice,String type){
    DiscountFunc func = DISCOUNT_MAP.get(type);
    if(func == null){
        throw new RuntimeException("优惠类型不存在");
    }
    //传入价格,执行Map中对应的Lambda代码
    return func.calc(originPrice);
}

新增优惠怎么加?

不用改 calcPrice 方法,只在 static 代码块新增一行 put

//新增优惠券满200减50
DISCOUNT_MAP.put("COUPON",p->p.compareTo(BigDecimal.valueOf(200))>=0
        ?p.subtract(BigDecimal.valueOf(50)):p);

完美符合开闭原则:对扩展开放、对修改关闭

四、通用扩展:4 种高频业务场景替换 if-else

场景 1:数据校验多分支(不同字段不同校验规则)

@FunctionalInterface
interface CheckRule{
    void check(String val);
}
Map<String,CheckRule> ruleMap = new HashMap<>();
static{
    ruleMap.put("phone",s->{if(s.length()!=11)throw new RuntimeException("手机号错误");});
    ruleMap.put("email",s->{if(!s.contains("@"))throw new RuntimeException("邮箱错误");});
}
//通用校验
public void checkField(String fieldType,String value){
    ruleMap.get(fieldType).check(value);
}

场景 2:文件解析(不同后缀不同解析逻辑:txt/excel/pdf)

@FunctionalInterface
interface FileParse{
    void parse(String path);
}
Map<String,FileParse> parseMap = Map.of(
        "txt",p-> System.out.println("解析txt文件:"+p),
        "excel",p-> System.out.println("解析excel:"+p)
);

场景 3:支付渠道(微信 / 支付宝 / 银联)经典替换

@FunctionalInterface
interface PayFunc{
    void pay(BigDecimal money);
}
Map<String,PayFunc> payMap = Map.of(
        "WECHAT",m-> System.out.println("微信支付"+m),
        "ALI",m-> System.out.println("支付宝支付"+m)
);
//统一支付入口
public void pay(String channel,BigDecimal money){
    payMap.get(channel).pay(money);
}

场景 4:Stream 中多条件筛选(替换多层 if 筛选)

//不用if判断条件类型,Predicate存不同筛选逻辑
Map<String, Predicate<User>> filterMap = Map.of(
        "ADULT",u->u.getAge()>=18,
        "MALE",u->"男".equals(u.getSex())
);
//动态传入筛选key
List<User> filter(List<User> list,String filterKey){
    Predicate<User> pred = filterMap.get(filterKey);
    return list.stream().filter(pred).collect(Collectors.toList());
}

五、进阶:动态临时传 Lambda(不用提前存 Map)

某些临时分支,调用时直接传入代码,完全消灭 if:

//通用执行方法
public <T,R> R exec(T param, Function<T,R> func){
    return func.apply(param);
}
//需要满减:传入满减逻辑
exec(new BigDecimal(200),p->p.subtract(BigDecimal(20)));
//需要折扣:传入折扣逻辑
exec(new BigDecimal(200),p->p.multiply(new BigDecimal("0.8")));

六、核心优缺点总结

✅优点

  1. 消灭臃肿 if/else,代码清爽
  2. 新增分支不用修改核心方法,只新增 Lambda 配置,开闭原则;
  3. 分支逻辑统一管理,便于维护、拆分、单元测试;
  4. 复用通用模板代码,避免重复造轮子。

❌缺点

分支极少(≤2 个)没必要过度使用,简单 if 更直观。

七、选型落地规范(项目开发准则)

  1. 分支≥3 种、未来大概率新增 → Lambda+Map 替换 if;
  2. 分支 1~2 种固定不变 → 普通 if 更简洁;
  3. 分支动态临时传入 → 直接入参传 Lambda,不用 Map。

八、和策略模式关系(面试必问)

  1. 传统策略:每个策略新建实现类,类多繁琐;
  2. Lambda 策略:用 Lambda 替代策略实现类,代码内联,极简实现策略模式,这就是 Lambda 干掉 if 的底层思想。

九、背诵口诀

if 分支变映射,函数接口做载体;分支逻辑 Lambda,存入 Map 里做配置;新增分支不用改,只添一行 put;少写 if 少嵌套,开闭原则稳落地。

十、面试简答一句话

利用行为参数化,将各个 if 内的业务代码封装为 Lambda 表达式,以 key-value 存入 Map,通过 key 匹配执行对应逻辑,从根源消除大量 if-else 分支代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值