Java8,函数式编程应用:

持续更新中:

函数式(Functional)接口 什么是函数式(Functional)接口 只包含一个抽象方法的接口,称为函数式接口。

你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式
抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽 象方法上进行声明)。

我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检 查它是否是一个函数式接口。同时 javadoc
也会包含一条声明,说明这个 接口是一个函数式接口。

在java.util.function包下定义了Java 8 的丰富的函数式接口:

package com.ly.frauddataplatform.luoyan;//TODO: 需要在接口上定义@FunctionalInterface注解,表示这是一个函数式的接口
//TODO: MyFunc<R,T>这里是标明泛型
@FunctionalInterface
public interface MyFunc<R,T> {/*** @Author luoyan* @Description: 函数式编程* @Date 2024/3/4 20:42* @param t: 入参,泛型可以传任何类型* @return R: 返回参数,泛型可以传任何类型**/R getValue(T t);
}

这里是自定义的函数式编程的自定义的实现接口方式:

    //TODO: 这里自定义一个方法,这个方法可以实现前置通知,后置通知,可以在调用方法的前后做一些公用的操作.//TODO: 在调用到自己的实现方法中的时候,去设计实现自己所需要的代码逻辑流程./*** @Author luoyan* @Description: 封装的方法,泛型中<R,T>:这个是声明泛型,R:返回的类型,也可以修改R为String,T为String.那么入参和出现就必须是String的类型.* @Date 2024/3/4 20:46 * @param myFunc: 这个是函数方法* @param name: 入参* @return R**/public <R,T> R toUpDate(MyFunc<R, T> myFunc, T name){System.out.println("前置通知");//TODO: 调用自己设定订代码逻辑流程.R value = myFunc.getValue(name);System.out.println(value);System.out.println("后置通知");return myFunc.getValue(name);}//TODO: 使用一个方法进行测试.@Testpublic void testDemoOne(){//TODO: 这里实现自己的代码逻辑.//TODO: 这里name是T,也就是入参,"1231"是R,也就是出参,可以自己随意定义,因为是泛型.String s = toUpDate(str -> {System.out.println(str);return "1231";}, true);System.out.println(s);}

Predicate:函数接口

Predicate<Integer> predicate = n ->{if (n > 4){return true;}return false;
};Predicate<Integer> and = predicate.and(k -> {if (k < 6) {return true;}return false;
}).or(t -> {if (t == 10) {return true;}return false;
});
boolean test1 = and.test(5);
System.out.println(test1);

在这里插入图片描述

这里使用:Function接口来实现。此接口的特点:有入参,有出参,可以直接很好的使用。还有其他的函数。
在这里插入图片描述
比如:只需要入参,不需要出参,可以根据自己的情况而定。
在这里插入图片描述

举一个例子:
比如我们要使用前置要做的事情,然后调用方法自己的逻辑,最后在执行一个后置要做的事情,其中前置流程和后置流程都是共有的流程。那么就可以使用函数式的变成去封装方法,然后每个地方都可以直接调用。这样很方便。

如果没有函数式编程,我们可能会想到反射的方式,传入一个类,一个方法,然后通过反射的方式去调用这个类中的某个方法,从而可以达到这种实现,但是太麻烦了。

目前我们需要对于redis进行上锁,然后解锁,中间是走自己的流程,那么我们就可以使用函数式编程:

package com.elong.fraud.rcenginedataconvert.constants;import com.elong.fraud.rcenginedataconvert.model.dto.TryLockParamData;
import com.ly.tcbase.cacheclient.CacheClientHA;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;import javax.annotation.Resource;
import java.util.UUID;
import java.util.function.Function;/*** @Author luoyan* @Description: redis锁* @Date 2024年01月18日 10:38* @Version: V1.0*/
@Component
public class RedissionTemplate {@Resourceprivate CacheClientHA cacheClientHa;/*** @Author luoyan* @Description:* @Date 2024/1/19 15:15* @param tryLockParamData: 入参值.*                        LockKey:key,*                        param:请求参数* @param consumer: Function<T,R> *                T:入参,*                R:返回参数* @return R**/public <R> R tryLock(TryLockParamData tryLockParamData, Function<Object,R> consumer){//TODO: 前置通知,对于参数进行校验String lockKey = tryLockParamData.getLockKey();if (ObjectUtils.isEmpty(lockKey)){return null;}//TODO: 前置通知,进行上锁String lockVal = UUID.randomUUID().toString();Boolean lock = cacheClientHa.String().setnx(lockKey, 60L, lockVal);try {long millis = System.currentTimeMillis();while (!lock) {//等待锁释放try {if (System.currentTimeMillis() - millis > 3000) {throw new RuntimeException("程序异常,未获取锁!");}Thread.sleep(100);} catch (Exception ignore) {}lock = cacheClientHa.String().setnx(lockKey, 60L, lockVal);}//TODO: 这里去调用自己的代码流程return consumer.apply(tryLockParamData.getParam());}finally {//TODO: 后置通知,去进行解锁。if (lockVal.equals(cacheClientHa.String().setcas(lockKey, lockVal, lockVal))) {cacheClientHa.Key().del(lockKey);}}}
}

第一处调用:

private JSONObject saveOrUpdateOriginData(JSONObject newValue, String uniqueId, String sourceName) {//分布式锁String lockKey = String.format(RedisCacheConstants.DATA_SOURCE_DETAIL_LOCK_FORMAT, sourceName, uniqueId);//TODO:new TryLockParamData(lockKey):入参。逗号后面就是函数方法,也就是自己的代码逻辑。JSONObject newValReturn = redissionTemplate.tryLock(new TryLockParamData(lockKey), consumer -> {//TODO: 自己的代码逻辑流程,先上锁,然后走这里的代码逻辑流程,最后进行解锁。return newVal;});return newValReturn == null ? new JSONObject() : newValReturn;
}

第二处调用:

//分布式锁
String lockKey = String.format(RedisCacheConstants.FEATURE_LIST_UPDATE_LOCK_FORMAT, uniqueId);
//TODO:new TryLockParamData(lockKey):入参。逗号后面就是函数方法,也就是自己的代码逻辑。
redissionTemplate.tryLock(new TryLockParamData(lockKey), rLock -> {//TODO: 自己的代码逻辑流程,先上锁,然后走这里的代码逻辑流程,最后进行解锁。//先执行更新,更新失败执行插入int update = dcdbFraudMapper.update(origin.getTableName(), fieldList, StrUtil.toUnderlineCase(origin.getUpdateKey()), uniqueId);if (update == 0) {boolean insert = dcdbFraudMapper.insert(origin.getTableName(), fieldList);}return null;
});

可以看到上面两处的调用使用函数式编程非常方便且代码也很美观,不用其他的方式就能够快速的实现,对于同事的阅读和理解也是非常快速的。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Crossbar阵列的电路结构及其基本原理

忆阻器Crossbar阵列是一种先进的神经网络硬件实现技术&#xff0c;它利用忆阻器的物理特性来模拟神经网络中的突触连接&#xff0c;为人工智能和机器学习应用提供了一种高效、低能耗的计算平台。本文将深入探讨忆阻器Crossbar阵列的基本原理及其在Read&#xff08;读取&#xf…

运维随录实战(2)之k8s部署应用

一, 创建.gitlab-ci.yml文件 架构流程 文件内容 stages: #设置流水线模版- build # 编译- source2img- deploy # 发布variables: # 设置全局变量MAVEN_PATH: .m2MAVEM_IMAGE: maven:3.8.5-openjdk-17-slim # maven 打包使用的镜像MAVEN_CLI_OPTS: "-s $MAVEN_PATH/set…

稀碎从零算法笔记Day7-LeetCode:罗马数字转整数

题型&#xff1a;字符串转化、找规律 链接&#xff1a;13. 罗马数字转整数 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 …

【深圳五兴科技】Java后端面经

本文目录 写在前面试题总览1、java集合2、创建线程的方式3、对spring的理解4、Spring Boot 和传统 Spring 框架的一些区别5、springboot如何解决循环依赖6、对mybatis的理解7、缓存三兄弟8、接口响应慢的处理思路9、http的状态码 写在前面 关于这个专栏&#xff1a; 本专栏记录…

抖音视频下载软件|视频批量采集工具

便捷操作&#xff0c;高效采集 在快节奏的数字化时代&#xff0c;我们的视频下载软件提供了简单便捷的操作流程&#xff0c;让用户能够高效地采集所需视频内容。用户只需输入关键词并点击开始抓取&#xff0c;系统会自动搜索指定关键词下的抖音视频数据&#xff0c;并将待解析视…

C语言第三十五弹---文件操作(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 文件操作 1、为什么使用文件&#xff1f; 2、什么是文件&#xff1f; 2.1、程序文件 2.2、数据文件 2.3、文件名 3、二进制文件和文本文件 4、文件的打开和…

折线图 温度变化曲线图

代码详情介绍 导入必要的库&#xff1a; matplotlib.pyplot&#xff1a;用于绘图。 matplotlib.font_manager&#xff1a;用于设置中文字体。 datetime&#xff1a;用于处理日期和时间。 random&#xff1a;用于生成随机数。 numpy&#xff1a;用于生成arange函数的刻度。 设置…

Linux系统使用宝塔面板安装MySQL服务并实现公网远程访问本地数据库【内网穿透】

文章目录 前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道 4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 宝塔面板的简易操作性,使得运维难度降低,简化了Linux命令行进行繁琐的配置,下面简单几步,通过宝塔面板cp…

【C语言】Leetcode 876. 链表的中间节点

主页&#xff1a;17_Kevin-CSDN博客 专栏&#xff1a;《Leetcode》 题目 通过题目的要求可以判断出有两种示例要解决&#xff0c;一种是偶数节点的链表&#xff0c;一种是奇数节点的链表&#xff0c;应对这两种情况我们需要使程序对二者都可以兼容。 解决思路 struct ListNode…

微服务相关的核心概念及技术

RPC框架&#xff1a; 在微服务架构中&#xff0c;服务与服务之间要实现接口的调用我们肯定要通过相关的RPC(Remote Procedure Call)框架来实现。 常用的RPC框架有:Dubbo&#xff0c;Google的GRPC&#xff0c;Apache的Thrift&#xff0c;微博的Motan&#xff0c;京东的EasyRPC等…

解密Lawnchair:打造个性化极致的Android桌面体验

解密Lawnchair&#xff1a;打造个性化极致的Android桌面体验 1. 简介 Lawnchair是一款知名的Android桌面定制工具&#xff0c;旨在为用户提供个性化极致的桌面体验。作为一个开源项目&#xff0c;Lawnchair融合了简洁、灵活和强大的特点&#xff0c;让用户能够自由定制其Andro…

低代码平台开发——基于React(文末送书)

目录 小程一言适用对象本书达成 书籍介绍作者简介内容介绍书籍目录阅读指导 小程送书 小程一言 《低代码平台开发——基于React》这本书主要围绕低代码平台和React技术的结合展开&#xff0c;为读者提供了关于低代码平台开发的理论和实践知识。 ## 书中内容简介 书中内容分为…