Lambda|行为参数化 完整精讲

一、核心一句话(必背)

行为参数化:把「可变的业务逻辑(一段代码 / 行为)当作参数传递进方法」,同一个方法,传入不同行为,实现不同业务,消除大量重复 if-else、重复方法,避免重复造轮子。

传统编码:参数只能传数值、对象;行为参数化:代码逻辑也能当参数,是 Lambda 核心思想。

二、为什么需要行为参数化(传统代码痛点)

场景:筛选商品,示例痛点

需求 1:筛选价格 > 100 的商品需求 2:筛选分类 = 手机的商品需求 3:筛选价格 > 50 并且分类 = 电脑

传统写法缺点:

  1. 每多一个筛选规则,新建一个筛选方法 → 方法泛滥、重复循环代码
  2. 修改筛选条件就要改方法,开闭原则差
java 复制代码
// 方案差:一个条件一个方法
List<Goods> filterByPrice(List<Goods> list,Integer price){}
List<Goods> filterByCategory(List<Goods> list,String category){}

行为参数化解决方案:只写 1 个通用 filter 方法,筛选规则通过入参传入

三、演进路线(从原始→匿名内部类→Lambda,循序渐进理解)

步骤 1:定义函数式接口(承载行为)

函数式接口:只有一个抽象方法的接口,用来封装一段行为逻辑

java 复制代码
@FunctionalInterface // 标记:只能一个抽象方法
public interface GoodsPredicate {
    // 参数:单个商品;返回:true/false 是否满足筛选条件
    boolean test(Goods goods);
}

步骤 2:编写通用过滤方法(固定逻辑:遍历集合;变化逻辑:判断规则→接口参数)

java 复制代码
public static List<Goods> filterGoods(List<Goods> list, GoodsPredicate predicate){
    List<Goods> res = new ArrayList<>();
    for(Goods g : list){
        // 调用传入的行为逻辑
        if(predicate.test(g)){
            res.add(g);
        }
    }
    return res;
}

固定逻辑:循环遍历封装一次;变化逻辑:外部传入,这就是行为参数化精髓

步骤 3:三代调用写法对比

  1. 第一代:自定义实现类(笨重,新增规则新建类)
java 复制代码
class PriceOver100 implements GoodsPredicate{
    @Override
    public boolean test(Goods g) {return g.getPrice()>100;}
}
//调用
filterGoods(list,new PriceOver100());
  1. 第二代:匿名内部类(省去实体类,但代码冗余)
java 复制代码
filterGoods(list, new GoodsPredicate() {
    @Override
    public boolean test(Goods g) {
        return "手机".equals(g.getCategory());
    }
});
  1. 第三代:Lambda 表达式(行为参数化最终形态,极简)
java 复制代码
// 筛选价格>100
filterGoods(list,g->g.getPrice()>100);
// 筛选分类电脑
filterGoods(list,g->"电脑".equals(g.getCategory()));

直接把判断逻辑(行为)作为第二个参数传入,不用新建类、不用匿名类

四、核心三大关键点(理解必背)

  1. 函数式接口是载体 :承载要传递的行为,@FunctionalInterface注解约束
  2. 行为作为入参:方法形参定义为接口类型,调用时传入 Lambda(具体实现逻辑)
  3. 固定逻辑抽进方法,变化逻辑外部传入,一套方法适配 N 种业务

五、项目中四大落地运用场景(高频实战)

场景 1:集合筛选、排序、遍历(Stream 全套底层都是行为参数化)

java 复制代码
List<Goods> goodsList;
// 筛选
List<Goods> phones = goodsList.stream().filter(g->"手机".equals(g.getCategory())).collect(Collectors.toList());
// 排序:排序规则作为参数
goodsList.sort((g1,g2)->g1.getPrice().compareTo(g2.getPrice()));
// 遍历:消费行为传入
goodsList.forEach(g-> System.out.println(g.getName()));
  • filter 参数Predicate、sort 参数Comparator、forEach 参数Consumer全是 JDK 内置函数式接口。

场景 2:自定义统一工具类(通用校验、统一处理器)

比如统一 Excel 导入:固定逻辑(读取文件、捕获异常),变化逻辑(每行数据保存逻辑通过 Lambda 传入)

java 复制代码
//通用导入模板
public static <T> void importExcel(File file, Consumer<T> saveFunc){
    //固定:解析excel
    List<T> data = parseExcel(file);
    for(T item:data){
        saveFunc.accept(item); //外部传入保存逻辑
    }
}
//使用:传入不同保存逻辑
importExcel(file,user->userService.save(user));
importExcel(file,order->orderService.save(order));

场景 3:策略逻辑替换大量 if else(替代策略模式手写类)

比如优惠计算:统一结算方法,优惠策略通过 Lambda 传入

java 复制代码
@FunctionalInterface
interface Discount{
    BigDecimal calc(BigDecimal money);
}
BigDecimal settle(BigDecimal money,Discount discount){
    return discount.calc(money);
}
//满减
settle(new BigDecimal(200),m->m.compareTo(new BigDecimal(100))>0?m.subtract(new BigDecimal(20)):m);
//折扣
settle(new BigDecimal(200),m->m.multiply(new BigDecimal("0.8")));

场景 4:线程任务、异步回调

Thread(Runnable):Runnable 是函数式接口,任务行为通过 Lambda 传入

java 复制代码
new Thread(()-> System.out.println("执行任务")).start();

六、JDK 四大内置核心函数式接口(背诵,日常 90% 场景够用)

表格

接口 抽象方法 用途
Predicate<T> boolean test(T t) 判断筛选:filter、条件校验
Consumer<T> void accept(T t) 消费处理:forEach、数据保存
Function<T,R> R apply(T t) 类型转换:map,T 转 R
Supplier<T> T get() 对象供给:创建对象、延迟获取数据

示例快速使用:

java 复制代码
//Function:字符串转Integer
Function<String,Integer> func = s->Integer.parseInt(s);
Integer num = func.apply("123");

七、行为参数化优点(面试简答)

  1. 代码复用:固定逻辑只写一次,减少重复代码,不重复造轮子
  2. 扩展性极强:新增业务规则不用新增方法 / 实体类,直接传 Lambda
  3. 消除臃肿 if-else、过多实体类,代码简洁
  4. 配合 Stream,简化集合操作

八、易混点总结

  1. Lambda 本质:函数式接口的实例,是行为参数化的语法糖;
  2. 行为参数化本质:把可变算法抽离为入参,面向接口、开闭原则落地;
  3. 没有函数式接口,就无法实现行为参数化。

九、背诵口诀

行为参数化,逻辑当参数; 函数接口做载体,Lambda 传行为; 固定代码写内部,变化规则外部给; 筛选排序和回调,四大接口全搞定。

相关推荐
garmin Chen1 小时前
Prompt工程入门:让AI按你的要求工作(3)--Prompt工程与提示词安全评测概述
java·人工智能·python·安全·prompt
阿正的梦工坊1 小时前
【Rust】05-结构体、枚举与模式匹配
java·数据库·rust
阿正的梦工坊1 小时前
【Rust】10-Cargo、测试与实用开发工作流
java·rust·log4j
用户298698530141 小时前
Java 实战:Word 文档中超链接的添加与自定义技巧
java·后端
swordbob1 小时前
Spring事务失效的场景
java·开发语言·spring
Devin~Y1 小时前
大厂 Java 面试实战:从 Spring Boot 微服务到 AI RAG 音视频平台全链路解析
java·spring boot·redis·spring cloud·微服务·rag·spring ai
让我上个超影吧1 小时前
Cluade code:Subagents (子代理)
java·ai
aXin_ya2 小时前
乐尚代驾,总结
java
仙俊红2 小时前
Java JUC:CompletableFuture 详解,多个任务并行执行并等待全部完成
java·python·spring