函数式接口与回调函数实践

news2024/11/28 2:31:45

函数式接口与回调函数实践

一、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表达式,可以轻松实现类似的效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2227736.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小米迎来「新起点」:硬核创新从超越到引领,小米SU7 Ultra 发布

发布 | 大力财经 10月29日&#xff0c;小米15系列暨小米澎湃OS 2新品发布会在北京召开&#xff0c;小米集团创始人、董事长兼CEO雷军宣布了小米汽车原型车在纽北跑出6分46秒874的圈速&#xff0c;登顶“纽北全球最速四门车”的好消息&#xff0c;并领衔发布了小米15系列手机、…

Go语言优秀的web框架推荐-酒香也怕巷子深 好的框架也需要宣传

温馨提示&#xff1a;我们分享的文章是给需要的人&#xff0c;不需要的人请绕过&#xff0c;文明浏览&#xff0c;误恶语伤人&#xff01; 前言 俗话说得好“酒香也怕巷子深”&#xff0c;好的东西不宣传也不能让大家知晓&#xff01;需要的人无法获取好的东西&#xff0c;好…

双十一特辑,解决铲屎官难题——性价比高的宠物空气净化器推荐

谁家好人受得了猫咪这么掉毛啊&#xff01;最近换季&#xff0c;掉毛情况越发严重&#xff0c;家里都快被毛发淹没了。每天下班回来&#xff0c;第一件事就是清扫一地的猫毛。那就算了&#xff0c;一呼吸还收获一鼻子浮毛&#xff0c;又是沉重一击&#xff0c;这日子快要没法过…

如何在 Windows 上安装 Python:一步一步的指南

Python 已成为 当今最受欢迎的编程语言之一&#xff0c;在商业的各个领域中广泛应用。开发者使用 Python 构建应用程序和开发网站&#xff0c;而数据工程师则使用 Python 进行数据分析、统计分析以及构建机器学习模型。 检测是否已安装Python 默认情况下&#xff0c;Windows …

自动驾驶-传感器简述

自动驾驶车辆上的传感器类型包含激光雷达、毫米波雷达、相机、imu、rtk、超声波雷达等&#xff0c;这些传感器用来接收外部世界多姿多彩的信号&#xff0c;根据接收到的信号&#xff0c;车载大脑对信号进行处理&#xff0c;那信号的准确程度就尤为重要。 本文将各个传感器的特性…

文本列的性能优化?深入Oracle全文索引

一.什么是全文索引&#xff1f; 全文索引通过分析和处理文本&#xff0c;将文档中的单词分解为词条&#xff08;tokens&#xff09;&#xff0c;然后存储词条与其所在文档的映射关系。这使得数据库可以快速定位包含特定关键字的记录&#xff0c;而不必对所有文本逐字匹配。 二…

解决IllegalAccessException: java.lang.Class<xxx.xActivity> is not accessible

异常信息 Caused by: java.lang.IllegalAccessException: java.lang.Class<com.xxx.xActivity> is not accessible from java.lang.Class<android.app.AppComponentFactory>at java.lang.Class.newInstance(Native Method)at android.app.AppComponentFactory.inst…

基于spootboot学生选课系统设计与实现

资料下载 https://download.csdn.net/download/qq_63753925/89888794 https://download.csdn.net/download/qq_63753925/89888793 https://download.csdn.net/download/qq_63753925/89885091 https://download.csdn.net/download/qq_63753925/89882320 摘 要 近年来&#xf…

计算机网络IP地址分类,子网掩码,子网划分复习资料

IP 地址的概念 IP 地址是独立于硬件地址的逻辑地址&#xff0c;它是由软件提供的地址。 IP 地址是网络层地址。 IP 编址方案和分类 IP 地址由 32 位二进制数构成&#xff0c;分为前缀(网络地址)和后缀(主机地址) 同一网段中每台计算机的 IP 地址是唯一的网络地址的分配全球…

山海鲸报表VS微软Power BI:哪个报表工具更适合企业?

在当今数据驱动的商业环境中&#xff0c;选择一款合适的报表工具对企业至关重要。山海鲸报表和微软Power BI都是广受欢迎的报表工具&#xff0c;但两者在功能、用户体验和应用场景上各有不同。那么&#xff0c;在实际使用中&#xff0c;究竟哪款工具更能满足企业需求呢&#xf…

【电子通识】四线制电阻屏怎么判断是哪一路出现异常?

在文章【电子通识】四线电阻屏原理中我们聊了一下四线电阻屏触摸的原理,如电阻屏结构、如何计算坐标等方面。 那么在实际的问题分析中,如果是屏硬件问题,那我们如何去判断到底是X还是Y出现异常或是说X+还是X-,是Y+还是Y-出现问题呢? 首先要知道,XY轴为什么会出问题,其实…

Linux基础环境搭建(CentOS7)- 安装Scala和Spark

#Linux基础环境搭建&#xff08;CentOS7&#xff09;- 安装Scala和Spark Linux基础环境搭建&#xff08;CentOS7&#xff09;- 安装Scala和Spark 大家注意以下的环境搭建版本号&#xff0c;如果版本不匹配有可能出现问题&#xff01;&#xff08;spark不要下2.4版本的 会报错…

EPLAN创建宏并自定义部件库详细案例操作(二)

#通过导入EDZ格式部件库的样式,模仿制作一个自定义的部件库# 续 EPLAN创建宏并自定义部件库详细案例操作(一) 需要宏文件(欧姆龙2D/3D),可以在此下载。 https://download.csdn.net/download/weixin_44166380/89933112 三、PLC地址编址 实际上,本操作可以忽略,但是如果…

国产系统安装Oracle报错处理

1.调用图形界面报错&#xff1a;已拒绝X11转移申请 解决方法&#xff1a;修改/etc/ssh_config 和/etc/sshd_config &#xff1a;X11Forwarding yes中和x11里no改为yes 2.开始安装./runInstaller提示 /u01/app/oracle/product/19.3.0.0/db_1/perl/bin/perl: error while loadi…

黑马数据库学习笔记

课程地址 &#xff08;基础篇&#xff09;MySQL的启动 mysql 默认使用 3306 端口 在 centos下&#xff0c;启动 mysql 数据库&#xff1a;service mysqld start; 查看状态/启动/停止/重启&#xff1a;systemctl status/start/stop/restart mysqld; 登录到mysql数据库&…

20241027_北京郊游香山公园

这次是第二次去香山公园&#xff0c;天气不是很晴朗&#xff0c;有雾。 乘坐地铁到的时候&#xff0c;第一趟车&#xff0c;我这么聪明&#xff0c;那肯定是不会坐的&#xff0c;因为没有座位&#xff0c;路程30多分钟&#xff0c;我都20多岁了&#xff0c;身体那肯定顶不住。 …

从0到1,AI我来了- (7)AI应用-ComfyUI-III-Flux模型

上篇我们利用已有的工作流&#xff0c;完成了一个已有comfyUi workflow 的美女制作&#xff0c;有美女&#xff0c;需要野兽来配&#xff0c;最近黑森林的Flux 很火&#xff0c;我们也来实践一下生成野猴子黑悟空。 这篇文章主要内容分三部分&#xff1a; 一、认识Flux&#…

【Linux系统编程】线程深入运用

目录 一&#xff0c;C线程与系统线程 二&#xff0c;分离线程 三&#xff0c;线程结构 四&#xff0c;__thread关键字 五&#xff0c;Linux线程互斥 1&#xff0c;线程互斥相关的背景概念 2&#xff0c;互斥锁 3&#xff0c;死锁 4&#xff0c;互斥锁的弊端 六&#…

【 C++ 】C++11的初步学习

目录 ​编辑 一、列表初始化 1.支持内置类型 2.支持自定义类型 二、initializer-list 三、右值引用和移动语义 1.左值和右值 a&#xff09;左值 b&#xff09;右值 2.左值引用和右值引用 a&#xff09;左值引用 b&#xff09;右值引用 c&#xff09;总结 d&#xf…

云计算平台上的DevOps实践

文章目录 什么是DevOps云计算平台上的DevOps优势自动化部署弹性伸缩地理分布 实施DevOps的关键组件版本控制系统持续集成/持续交付工具配置管理工具监控和日志管理 实践案例使用AWS CodePipeline进行持续集成/持续交付利用AWS Auto Scaling实现弹性使用AWS CloudFormation进行基…