当前位置: 首页 > news >正文

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.lryc.cn/news/230252.html

相关文章:

  • 【HUST】网安纳米|2023年研究生纳米技术考试参考
  • 【移远QuecPython】EC800M物联网开发板的MQTT协议腾讯云数据上报
  • 关灯游戏及扩展
  • 深度解析:用Python爬虫逆向破解dappradar的URL加密参数(最详细逆向实战教程,小白进阶高手之路)
  • 论文笔记:AttnMove: History Enhanced Trajectory Recovery via AttentionalNetwork
  • Django之视图层
  • DAY54 392.判断子序列 + 115.不同的子序列
  • 【Nginx】nginx | 微信小程序验证域名配置
  • 大数据Doris(二十二):数据查看导入
  • STM32 I2C详解
  • 软考 系统架构设计师系列知识点之云计算(1)
  • VS Code画流程图:draw.io插件
  • 计算机 - - - 浏览器网页打开本地exe程序,网页打开微信,网页打开迅雷
  • C_6练习题
  • XUbuntu22.04之安装pkg-config(一百九十二)
  • 【Proteus仿真】【51单片机】拔河游戏设计
  • 第3关:集合操作100
  • 八:ffmpeg命令提取像素格式和PCM数据
  • rinex3.04 导航文件
  • linux rsyslog日志采集格式设定二
  • 八股文-面向对象的理解
  • LeetCode【238】除自身意外的数组的乘积
  • c语言从入门到实战——基于指针的数组与指针数组
  • AUTOSAR汽车电子嵌入式编程精讲300篇-面向车载CAN网络的路由和ECU刷写方法
  • 软考 系统架构设计师系列知识点之云计算(3)
  • 【万字长文】Python 日志记录器logging 百科全书 之 日志过滤
  • redis基线检查
  • 第五章ARM处理器的嵌入式硬件系统设计——课后习题
  • Python - GFPGAN + MoviePy 提高人物视频画质
  • uniapp插件开发