Java封装一个根据指定的字段来获取子集的工具类

工具类

ZhLambdaUtils

@SuppressWarnings("all")
public class ZhLambdaUtils {/*** METHOD_NAME*/private static final String METHOD_NAME = "writeReplace";/*** 获取到lambda参数的方法名称** @param <T>      parameter* @param function function* @return the name* @since 2023.1.1*/public static <T> String getLambdaMethodName(FilterUtils.ZhFunction<T, ?> function) {try {return ((SerializedLambda) MethodUtils.invokeMethod(function, true, METHOD_NAME)).getImplMethodName();} catch (Exception e) {throw new RuntimeException(e);}}/*** Method to property** @param name name* @return the string* @since 2023.1.1*/public static String methodToProperty(String name) {if (name.startsWith("is")) {name = name.substring(2);} else {if (!name.startsWith("get") && !name.startsWith("set")) {throw new IllegalArgumentException("Error parsing property name '" + name + "'.  Didn't start with 'is', 'get' or 'set'.");}name = name.substring(3);}if (name.length() == 1 || name.length() > 1 && !Character.isUpperCase(name.charAt(1))) {name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);}return name;}/*** Is property** @param name name* @return the boolean* @since 2023.1.1*/public static boolean isProperty(String name) {return isGetter(name) || isSetter(name);}/*** Is getter** @param name name* @return the boolean* @since 2023.1.1*/public static boolean isGetter(String name) {return name.startsWith("get") && name.length() > 3 || name.startsWith("is") && name.length() > 2;}/*** Is setter** @param name name* @return the boolean* @since 2023.1.1*/public static boolean isSetter(String name) {return name.startsWith("set") && name.length() > 3;}}

SelectSubsetUtils

该工具类可以实现通过对象的指定字段实现双向遍历

/***  通过本级唯一key值,以及本级字段、父级字段迭查询所有本级的子集*/
@UtilityClass
public class SelectSubsetUtils {/*** Filter** @param <D>    parameter* @param origin 需要被过滤的数据集* @param left   本级唯一key -例如code* @param right  本级与父级关联key值 -例如parentCode* @param adjust 本级唯一key值过滤条件* @return the list* @since 2023.1.1*/public static <D> List<D> filterSon(List<D> origin, ZhFunction<D, ?> left, ZhFunction<D, ?> right, Adjust adjust) {return filter(origin, left, right, adjust, false);}/*** Filter parent** @param <D>    parameter* @param origin 需要被过滤的数据集* @param left   本级唯一key -例如code* @param right  本级与父级关联key值 -例如parentCode* @param adjust 本级唯一key值过滤条件* @return the list* @since 2023.1.1*/public static <D> List<D> filterParent(List<D> origin, ZhFunction<D, ?> left, ZhFunction<D, ?> right, Adjust adjust) {return filter(origin, left, right, adjust, true);}/*** Filter** @param <D>      parameter* @param origin   origin* @param left     left* @param right    right* @param adjust   adjust* @param reverset reverset* @return the list* @since 2023.1.1*/private static <D> List<D> filter(List<D> origin, ZhFunction<D, ?> left, ZhFunction<D, ?> right,Adjust adjust, Boolean reverset) {//过滤全量数据按照本级唯一key进行过滤List<D> ds = origin.stream().filter(o -> {//通过反射获取到传递进来的本级唯一key值Object value = getObject(left, o);return adjust.test(value);}).collect(Collectors.toList());//调用与父级关联的key值进行递归过滤if (reverset) {// 如果是反转,那么就是父级过滤return filter(origin, ds, left, right);} else {// 如果是正常,那么就是子级过滤return filter(origin, ds, right, left);}}/*** Filter** @param <D>    parameter* @param origin 需要被过滤的数据源* @param filter 被过滤后的数据集* @param left   本级唯一key -例如code* @param right  本级与父级关联key值 -例如parentCode* @return the list* @since 2023.1.1*/private static <D> List<D> filter(List<D> origin, List<D> filter, ZhFunction<D, ?> left, ZhFunction<D, ?> right) {//构建本级过滤的数据,然后拿出来跟全量数据再次进行比对List<D> list = new LinkedList<>(filter);if (CollectionUtils.isEmpty(filter)) {return list;}//遍历过滤后的数据集filter.forEach(f -> {//跟全量的数据进行比较List<D> ds = origin.stream().filter(o -> {//将全量的数据和过滤出的数据进行比较,找出后续的子节点Object value = getObject(left, o);Object value2 = getObject(right, f);return value.equals(value2);}).collect(Collectors.toList());if (CollectionUtils.isEmpty(ds)) {return;}//递归调用list.addAll(filter(origin, ds, left, right));});return list;}/*** 获取值** @param <D>        parameter* @param firstFiled first filed* @param d          d* @return object object* @since 2023.1.1*/private static <D> Object getObject(ZhFunction<D, ?> firstFiled, D d) {String lambdaMethodName = ZhLambdaUtils.getLambdaMethodName(firstFiled);//获取到字段名称String fieldName = ZhLambdaUtils.methodToProperty(lambdaMethodName);Object value = null;try {Field field = FieldUtils.getDeclaredField(d.getClass(), fieldName, true);value = field.get(d);} catch (Exception e) {throw new RuntimeException(e);}return value;}/*** 自定义判断函数*/@FunctionalInterfacepublic interface Adjust {/*** Test** @param value value* @return the boolean* @since 2023.1.1*/boolean test(Object value);}/*** 自定义 Serializable 函数接口,这个接口有大用,至于为什么可以看下面参考博客*/@FunctionalInterfacepublic interface ZhFunction<T, R> extends Function<T, R>, Serializable {}}

测试

寻找字段 Code 为 1681497872765722624,并且关联的父级code为 ParentCode 的所有子集

public static void main(String[] args) {List<A> list = new ArrayList<>();A a = new A("1", "1681497872765722624");A a2 = new A("1681497872765722624", "1681498005196677120");A a3 = new A("1681497872765722624", "1681498062989991936");A a4 = new A("1681497872765722624", "1681498151091347456");A a5 = new A("1681498151091347456", "2");A a6 = new A("1681498151091347456", "3");A a7 = new A("8", "7");A a8 = new A("", "8");list.add(a);list.add(a2);list.add(a3);list.add(a4);list.add(a5);list.add(a6);list.add(a7);list.add(a8);List<A> target = filter(list, A::getCode, A::getParentCode, "1681497872765722624"::equals);target.forEach(System.out::println);
}

在这里插入图片描述

参考文档:
函数接口实现Serializable的用处说明

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

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

相关文章

全志R128基础组件开发指南——图像采集

图像采集 CSI&#xff08;DVP&#xff09; 图像采集 SENSOR -> CSI 通路 CSI &#xff08;CMOS sensor interface&#xff09;接口时序上可支持独立 SYNC 和嵌入 SYNC(CCIR656)。支持接收 YUV422 或 YUV420 数据。 VSYNC 和HSYNC 的有效电平可以是正极性&#xff0c;也可…

流量分析(5.5信息安全铁人三项赛数据赛题解)

黑客通过外部的web服务器攻击到企业内部的系统中&#xff0c;并留下了web后门&#xff0c;通过外部服务器对内部进行了攻击。 目录 黑客攻击的第一个受害主机的网卡IP地址 黑客对URL的哪一个参数实施了SQL注入 第一个受害主机网站数据库的表前缀(加上下划线 例如abc_) 第一…

当路由器突然提示“未检测到入户网线”

找到浏览器的“安全DNS”&#xff0c;根据浏览器不同可能有差别。 开启安全DNS&#xff0c;使用“自定义” 地址用阿里的&#xff08;其它的也行&#xff09;&#xff1a; https://dns.alidns.com/dns-query{?dns}

【工程部署】在RK3588上部署OCR(文字检测识别)(DBNet+CRNN)

硬件平台&#xff1a; 1、firefly安装Ubuntu系统的RK3588&#xff1b; 2、安装Windows系统的电脑一台&#xff0c;其上安装Ubuntu18.04系统虚拟机。 参考手册&#xff1a;《00-Rockchip_RKNPU_User_Guide_RKNN_API_V1.3.0_CN》 《RKNN Toolkit Lite2 用户使用指南》 1、文…

AI创作系统ChatGPT网站源码+支持最新GPT-Turbo模型+支持DALL-E3文生图/AI绘画源码

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

【uni-app + uView】CountryCodePicker 国家区号组件

1. 效果图 2. 组件完整代码 <template><u-popup class="country-code-picker-container" v-if="show" :show

基于Qt 多线程(继承 QObject 的线程)

​ 继承 QThread 类是创建线程的一种方法,另一种就是继承QObject 类。继承 QObject 类更加灵活。它通过 QObject::moveToThread()方法,将一个 QObeject的类转移到一个线程里执行。恩,不理解的话,我们下面也画个图捋一下。 通过上面的图不难理解,首先我们写一个类继承 QObj…

虹科示波器 | 汽车免拆检修 | 2021款广汽丰田威兰达PHEV车发动机故障灯异常点亮

一、故障现象 一辆2021款广汽丰田威兰达PHEV车&#xff0c;搭载A25D-FXS发动机和动力蓄电池系统&#xff08;额定电压为355.2V&#xff0c;额定容量为45.0Ah&#xff09;&#xff0c;累计行驶里程约为1万km。车主反映&#xff0c;高速行驶时发动机突然抖动&#xff0c;且发动机…

原生JS实现视频截图

视频截图效果预览 利用Canvas进行截图 要用原生js实现视频截图&#xff0c;可以利用canvas的绘图功能 ctx.drawImage&#xff0c;只需要获取到视频标签&#xff0c;就可以通过drawImage把视频当前帧图像绘制在canvas画布上。 const video document.querySelector(video) con…

在Vue.js中,什么是slot(插槽)?它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

解决Python中使用requests库遇到的身份验证错误

在使用requests库进行HTTP请求时&#xff0c;用户遇到了一个AuthenticationRequired&#xff08;身份验证必须&#xff09;的错误。然而&#xff0c;当使用urllib.request.urlopen执行相同的操作时&#xff0c;却能够成功。同时&#xff0c;用户提供了自己的系统信息&#xff0…

人工智能在现代科技中的应用和未来发展趋势

人工智能是一种基于计算机科学的技术&#xff0c;旨在智能地模拟人类的思维和行为。随着计算能力、数据存储和传输速度的提高&#xff0c;人工智能已经成为现代科技领域中的一个热门话题。本文将讲解人工智能在现代科技中的应用和未来发展趋势。 一、人工智能在现代科技中的应用…