一、核心一句话(必背)
传统: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("优惠类型不存在");
}
}
缺点:
- 新增「优惠券抵扣」,必须改方法加 else if;
- 分支臃肿、可读性差、维护难、重复造轮子。
三、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")));
六、核心优缺点总结
✅优点
- 消灭臃肿 if/else,代码清爽;
- 新增分支不用修改核心方法,只新增 Lambda 配置,开闭原则;
- 分支逻辑统一管理,便于维护、拆分、单元测试;
- 复用通用模板代码,避免重复造轮子。
❌缺点
分支极少(≤2 个)没必要过度使用,简单 if 更直观。
七、选型落地规范(项目开发准则)
- 分支≥3 种、未来大概率新增 → Lambda+Map 替换 if;
- 分支 1~2 种固定不变 → 普通 if 更简洁;
- 分支动态临时传入 → 直接入参传 Lambda,不用 Map。
八、和策略模式关系(面试必问)
- 传统策略:每个策略新建实现类,类多繁琐;
- Lambda 策略:用 Lambda 替代策略实现类,代码内联,极简实现策略模式,这就是 Lambda 干掉 if 的底层思想。
九、背诵口诀
if 分支变映射,函数接口做载体;分支逻辑 Lambda,存入 Map 里做配置;新增分支不用改,只添一行 put;少写 if 少嵌套,开闭原则稳落地。
十、面试简答一句话
利用行为参数化,将各个 if 内的业务代码封装为 Lambda 表达式,以 key-value 存入 Map,通过 key 匹配执行对应逻辑,从根源消除大量 if-else 分支代码。
2万+

被折叠的 条评论
为什么被折叠?



