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生成用户反馈信息
这种设计让代码更加灵活、可复用,并且符合函数式编程的思想。