Consumer 和 Function 接口详解
Consumer 和 Function 接口详解
1. Consumer 接口
基本定义
@FunctionalInterface
public interface Consumer<T> {void accept(T t);// 默认方法 - 组合多个Consumerdefault Consumer<T> andThen(Consumer<? super T> after) {Objects.requireNonNull(after);return (T t) -> { accept(t); after.accept(t); };}
}
核心特点
- 单抽象方法:只有
accept(T t)
一个抽象方法 - 消费型接口:接收参数但不返回值
- 副作用操作:通常用于产生副作用的操作(如修改对象、保存数据等)
使用示例
// 基本用法
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"));
在导入方法中的应用
// 教材建设的Consumer
Consumer<TSchoolEnterpriseCooperation> textbookProcessor = data -> this.insertTSchoolEnterpriseCooperation(data);// 相当于:
Consumer<TSchoolEnterpriseCooperation> textbookProcessor = new Consumer<>() {@Overridepublic void accept(TSchoolEnterpriseCooperation data) {insertTSchoolEnterpriseCooperation(data);}
};
2. Function 接口
基本定义
@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));}// 组合函数 - 先执行当前函数,再执行afterdefault <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;}
}
核心特点
- 转换型接口:接收一个参数,返回一个结果
- 无副作用:理想情况下应该是纯函数(不修改输入参数)
- 类型转换:常用于数据转换、映射操作
使用示例
// 字符串转换
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"
在导入方法中的应用
// 生成标识信息的Function
Function<TSchoolEnterpriseCooperation, String> identifierProvider = data -> "ID:" + data.getId() + " Name:" + data.getBookName();// 相当于:
Function<TSchoolEnterpriseCooperation, String> identifierProvider = new Function<>() {@Overridepublic String apply(TSchoolEnterpriseCooperation data) {return "ID:" + data.getId() + " Name:" + data.getBookName();}
};
3. 两个接口的对比
特性 | Consumer | Function |
---|---|---|
返回值 | void(无返回值) | 有返回值(类型R) |
用途 | 执行操作、产生副作用 | 数据转换、计算返回值 |
方法 | accept(T t) | apply(T t) |
类比 | 命令模式 | 策略模式 |
4. 在导入方法中的协同工作
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. 实际业务示例
// 用户导入
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(), // Functiontrue);
}
6. 高级用法
Consumer 链式操作
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 组合转换
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生成用户反馈信息
这种设计让代码更加灵活、可复用,并且符合函数式编程的思想。