函数式接口与回调函数实践
一、Java 的函数式接口
是指仅包含一个抽象方法的接口,通常用于 lambda 表达式或方法引用。Java 8 引入了很多内置的函数式接口,比如 Runnable、Callable、Predicate、Function、Consumer 等
演示,数据类型转换的函数式接口的简单使用
step 1 定义函数式接口
@FunctionalInterface
public interface ConvertFunctionalInterface<F, T> {
/**
* 把F转换为T 类型
* @param form 输入对象 F
* @return 输出对象 T
*/
T convert(F form);
}
step 2 定义同一调用方法类
public class DataConvert{
/**
* 把F转换为T 类型
* @param data 输入对象 F
* @return 输出对象 T
*/
public static <F, T> T processData(F data, ConvertFunctionalInterface<F, T> functional) {
return functional.convert(data);
}
}
step 3.定义数据类型转换方法
public class BuildObjTool {
public static FillTaskSqlEntity buildFillTaskSql(FillTaskSqlDTO fillTask) {
FillTaskSqlEntity fillTaskSql = new FillTaskSqlEntity();
fillTaskSql.setExecuteSql(fillTask.getExecuteSql());
fillTaskSql.setBatch(fillTask.getBatchTime());
return fillTaskSql;
}
public static ValidTableFieldReqDTO buildValidTableField(CreateTableRelateReqDTO createTable){
ValidTableFieldReqDTO valid = new ValidTableFieldReqDTO();
valid.setUserId(createTable.getUserId());
valid.setEnterpriseId(createTable.getEnterpriseId());
valid.setCollectionTarget(createTable.getCollectionTarget());
}
}
step 4 代码中使用示例
FillTaskSqlEntity fillTask = DataConvert.processData(fillTaskSql, BuildObjTool::buildFillTaskSql);
写到这里,似乎还没体会到函数式接口的好处吧?
如果第二处涉及类型转换,那么,如下:
ValidTableFieldReqDTO valid = DataConvert.processData(createTableRelateReqDTO, BuildObjTool::buildValidTableField);
如果涉及几十处类型转换,那么,对外的转换接口只有这一个,自己传入入参对象,转换方法,以及接收对象。
函数式接口极大地提高了 Java 的灵活性和可读性,使得许多编程模式更为简洁和易于理解。它们在事件处理、异步编程、策略模式以及集合处理等多个场景中都得到了广泛应用
二、回调函数
回调(Callback)是一种编程模式,其中一个函数(或方法)在执行完成后通过调用另一个函数(或方法)来传递执行结果,或在特定事件发生时调用。这种模式常用于异步操作、事件驱动编程中,可以提升代码的可扩展性、灵活性和模块化
示例1:有返回值的,同步调用案例:
step 1 定义回调接口
interface Callback3 {
String onComplete(String result);
}
step 2 定义任务类
class Task3 {
public String execute(Callback3 callback3) {
// 模拟一些业务逻辑处理
String result = "模拟一些业务逻辑处理!";
System.out.println("step 1…………………execute……………");
// 回调通知调用方
String res = callback3.onComplete(result);
return res;
}
}
step 3 业务调用
public static void main(String[] args) {
Task3 task3 = new Task3();
// 通过匿名类实现回调
String res = task3.execute(result -> {
System.out.println("step 2.Callback received: " + result);
return "我是中国";
});
System.out.println("main ======res:"+res);
}
示例2:看一个创建无关系表中实际使用的回调函数:
step 1.创建回调接口
public interface CallBackInterface {
List<Map<String, Object>> onComplete(int maxLength);
}
step 2 回调方法类
public class CallBackTask {
public List<Map<String, Object>> execute(CallBackInterface callback, Map<String, List<Map<String, Object>>> result) {
// 贪心算法计算数据最长表
int maxLength = BuildObjTool.greedyAlgorithm(result);
return callback.onComplete(maxLength);
}
}
step 3 业务中调用
CallBackTask callBackTask = new CallBackTask();
List<Map<String, Object>> buildRespList = callBackTask.execute(res -> BuildObjTool.buildEachTableDataResp(result, createTableInfo, res), result);
复盘一下:
1.业务调用,首先进入CallBackTask 执行execute方法
2.CallBackTask 的execute方法,返回贪心算法得到的长度maxLength
3.回调再调用业务方法中的BuildObjTool.buildEachTableDataResp(result, createTableInfo, res) 执行完返回得到的buildRespList
总路线:业务-->回调任务--->业务
其中用到的工具方法:
public class BuildObjTool {
//贪心算法
public static int greedyAlgorithm(Map<String, List<Map<String, Object>>> result) {
int max = 0;
for (List<Map<String, Object>> list : result.values()) {
int length = list.size();
max = Math.max(max, length);
}
return max;
}
//把数据组装成List<Map>>结构
public static List<Map<String, Object>> buildEachTableDataResp(Map<String, List<Map<String, Object>>> result, CreateTableInfoReqDTO createTableInfo, int maxLength) {
List<Map<String, Object>> resp = new ArrayList<>();
List<CreateTableFieldReqDTO> tables = createTableInfo.getTables();
// 1.获取每张表对应取了哪些字段
Map<String, List<String>> tableFieldMap = tables.stream().collect(Collectors.toMap(CreateTableFieldReqDTO::getEntityName,
item -> item.getFields().stream().map(CreateTableFieldTypeReqDTO::getTargetFieldName).collect(Collectors.toList()), (k1, k2) -> k1));
// 2.循环-以最长元素集合为标准
for (int i = 0; i < maxLength; i++) {
Map<String, Object> map = new ConcurrentHashMap<>();
int finalI = i;
result.forEach((key, value) -> {
// 4.依次取每个表数据的第i条数据
int size = value.size();
Map<String, Object> eachMap;
if (size > finalI) {
eachMap = value.get(finalI);
} else {
eachMap = null;
}
List<String> fieldList = tableFieldMap.get(key);
// 5.获取字段对应的数据
fieldList.forEach(ite -> {
Object obj = null;
if (ObjectUtils.isNotEmpty(eachMap)) {
obj = eachMap.get(ite);
}
// 6.存储值到map---没有值的话去获取该字段对应类型的默认值
map.put(ite, Objects.nonNull(obj) ? obj : getFieldDefaultValue(ite, createTableInfo));
});
});
resp.add(map);
}
return resp;
}
}
总结:
Java中的回调机制(Callback)是实现异步编程、解耦代码、灵活处理任务的一种重要方式。通过回调,方法A可以在方法B完成时被通知并处理结果。Java的回调机制并不像JavaScript那样原生支持函数作为参数,但通过接口、匿名类或Lambda表达式,可以轻松实现类似的效果。