Consumer 和 Function 接口详解

Consumer 和 Function 接口详解

1. Consumer 接口

基本定义

java 复制代码
@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
    
    // 默认方法 - 组合多个Consumer
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

核心特点

  • 单抽象方法 :只有 accept(T t) 一个抽象方法
  • 消费型接口:接收参数但不返回值
  • 副作用操作:通常用于产生副作用的操作(如修改对象、保存数据等)

使用示例

java 复制代码
// 基本用法
Consumer<String> printer = str -> System.out.println(str);
printer.accept("Hello World"); // 输出:Hello World

// 对象操作
Consumer<List<String>> clearList = list -> list.clear();
List<String> names = new ArrayList<>(Arrays.asList("Alice", "Bob"));
clearList.accept(names); // 清空列表

// 方法引用
Consumer<User> saveUser = userService::save;
saveUser.accept(new User("John"));

在导入方法中的应用

java 复制代码
// 教材建设的Consumer
Consumer<TSchoolEnterpriseCooperation> textbookProcessor = 
    data -> this.insertTSchoolEnterpriseCooperation(data);

// 相当于:
Consumer<TSchoolEnterpriseCooperation> textbookProcessor = new Consumer<>() {
    @Override
    public void accept(TSchoolEnterpriseCooperation data) {
        insertTSchoolEnterpriseCooperation(data);
    }
};

2. Function 接口

基本定义

java 复制代码
@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
    
    // 组合函数 - 先执行before,再执行当前函数
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    
    // 组合函数 - 先执行当前函数,再执行after
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    
    // 恒等函数
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

核心特点

  • 转换型接口:接收一个参数,返回一个结果
  • 无副作用:理想情况下应该是纯函数(不修改输入参数)
  • 类型转换:常用于数据转换、映射操作

使用示例

java 复制代码
// 字符串转换
Function<String, Integer> stringToInt = str -> Integer.parseInt(str);
Integer number = stringToInt.apply("123"); // 返回 123

// 对象属性提取
Function<User, String> getName = user -> user.getName();
String name = getName.apply(user); // 返回用户名

// 方法引用
Function<String, String> toUpperCase = String::toUpperCase;
String result = toUpperCase.apply("hello"); // 返回 "HELLO"

// 组合函数
Function<Integer, Integer> multiplyBy2 = x -> x * 2;
Function<Integer, String> toString = x -> "Result: " + x;
Function<Integer, String> pipeline = multiplyBy2.andThen(toString);
String output = pipeline.apply(5); // 返回 "Result: 10"

在导入方法中的应用

java 复制代码
// 生成标识信息的Function
Function<TSchoolEnterpriseCooperation, String> identifierProvider = 
    data -> "ID:" + data.getId() + " Name:" + data.getBookName();

// 相当于:
Function<TSchoolEnterpriseCooperation, String> identifierProvider = new Function<>() {
    @Override
    public String apply(TSchoolEnterpriseCooperation data) {
        return "ID:" + data.getId() + " Name:" + data.getBookName();
    }
};

3. 两个接口的对比

特性 Consumer Function
返回值 void(无返回值) 有返回值(类型R)
用途 执行操作、产生副作用 数据转换、计算返回值
方法 accept(T t) apply(T t)
类比 命令模式 策略模式

4. 在导入方法中的协同工作

java 复制代码
public <T> String importData(List<T> dataList,
                            Consumer<T> processor,           // 处理数据(保存到数据库)
                            Function<T, String> identifierProvider, // 生成标识信息
                            boolean updateSupport) {
    
    for (T data : dataList) {
        try {
            // Consumer:执行数据保存操作
            processor.accept(data);  // 不关心返回值,只执行操作
            
            // Function:生成用于显示的消息标识
            String identifier = identifierProvider.apply(data);  // 关心返回值
            
            successMsg.append(identifier + " 导入成功");
        } catch (Exception e) {
            String identifier = identifierProvider.apply(data);
            failureMsg.append(identifier + " 导入失败");
        }
    }
}

5. 实际业务示例

java 复制代码
// 用户导入
public String importUsers(List<User> userList) {
    return importData(
        userList,
        user -> {
            // Consumer:保存用户,可能包含密码加密、权限设置等操作
            user.setPassword(encrypt(user.getPassword()));
            userService.save(user);
        },
        user -> "用户:" + user.getUsername() + " 邮箱:" + user.getEmail(), // Function:生成标识
        false
    );
}

// 产品导入
public String importProducts(List<Product> productList) {
    return importData(
        productList,
        product -> {
            // Consumer:保存产品,可能包含库存初始化等操作
            product.setStock(0);
            productService.save(product);
        },
        product -> "产品:" + product.getName() + " 编码:" + product.getCode(), // Function
        true
    );
}

6. 高级用法

Consumer 链式操作

java 复制代码
Consumer<String> logMessage = msg -> System.out.println("LOG: " + msg);
Consumer<String> saveToFile = msg -> fileService.write(msg);

// 组合多个Consumer
Consumer<String> pipeline = logMessage.andThen(saveToFile);
pipeline.accept("导入完成"); // 先打印日志,再保存到文件

Function 组合转换

java 复制代码
Function<String, Integer> parse = Integer::parseInt;
Function<Integer, String> format = num -> "Number: " + num;

// 组合转换:字符串 -> 整数 -> 格式化字符串
Function<String, String> process = parse.andThen(format);
String result = process.apply("123"); // "Number: 123"

总结

  • Consumer:用于"做事情",执行操作但不关心返回值
  • Function:用于"转换数据",接收输入并返回输出
  • 在导入方法中,两者完美配合:Consumer处理业务逻辑,Function生成用户反馈信息

这种设计让代码更加灵活、可复用,并且符合函数式编程的思想。

相关推荐
W.Buffer4 小时前
设计模式-工厂模式:解耦对象创建的设计艺术
java·开发语言·设计模式
四谎真好看4 小时前
Java 黑马程序员学习笔记(进阶篇20)
java·笔记·学习·学习笔记
BUTCHER54 小时前
【原理扫描】SSL/TLS 服务器瞬时 Difie-Hellman 公共密钥过弱
java·服务器·网络·ssl
聪明的笨猪猪4 小时前
hot 100 (1)—— 两数之和(哈希)
java·经验分享·算法·哈希算法
梵得儿SHI4 小时前
Java 注解与反射实战:自定义注解从入门到精通
java·开发语言·注解·自定义注解·元注解·控制注解的作用·声明式编程思想
速易达网络5 小时前
Java Web登录系统实现(不使用开发工具)
java·开发语言·前端
悟能不能悟5 小时前
java重构旧代码有哪些注意的点
java·开发语言·重构
怪兽20146 小时前
Redis过期键的删除策略有哪些?
java·数据库·redis·缓存·面试
workflower9 小时前
单元测试-例子
java·开发语言·算法·django·个人开发·结对编程