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

news2024/11/20 15:36:14

工具类

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;
    }

    /**
     * 自定义判断函数
     */
    @FunctionalInterface
    public interface Adjust {
        /**
         * Test
         *
         * @param value value
         * @return the boolean
         * @since 2023.1.1
         */
        boolean test(Object value);
    }

    /**
     * 自定义 Serializable 函数接口,这个接口有大用,至于为什么可以看下面参考博客
     */
    @FunctionalInterface
    public 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.coloradmin.cn/o/1210118.html

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

相关文章

RK3588平台开发系列讲解(项目篇)实时显示摄像头

文章目录 一、测试代码二、代码解析2.1、OpenCV头文件2.2、类与函数的访问方式2.3、捕获摄像头图像2.4、定义图像变量2.5、显示图像沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇将给大家介绍,如何基于USB摄像头进行实时显示。 一、测试代码 #include "o…

vue离线地图(瓦片)

最近公司要弄一个这样的离线地图&#xff0c;要求在图上打点画线之类的。折腾了几天&#xff0c;学习了三种方式&#xff1a; 1.拿到各省市区的经纬度json&#xff0c;通过echarts来制作&#xff0c;再套一个卫星图的地图背景 2.下载地图瓦片&#xff0c;再通过百度/高德的离线…

文章发表 | 求臻医学发布精准肿瘤学临床试验预筛选平台

近日&#xff0c;求臻医学信息与人工智能团队研发的精准肿瘤学临床试验预筛选平台OncoCTMiner&#xff0c;在线发表于国际期刊Database: The Journal of Biological Databases and Curation (IF5.8)。OncoCTMiner集成自然语言处理&#xff08;NLP&#xff09;和大型语言模型&am…

caspp attacker lab

attacker lab phase2 advice phase 1 ctarget 会先调用test , test调用getbuf, getbuf调用Get。 任务目的是通过缓冲区注入攻击&#xff0c;将函数getbuf返回直接重定向到函数touch1。 0x28 是 40 比特&#xff0c; gdb ./ctarget getbuf 下一次执行的指令是401976, rsp对…

【Python】上市公司数据进行经典OLS回归实操

一、题目二、数据合并、清洗、描述性统计1、数据获取2、数据合并3、选择董监高薪酬作为解释变量的理论逻辑分析 三、多元回归模型的参数估计、结果展示与分析1、描述性统计分析2、剔除金融类上市公司3、对所有变量进行1%缩尾处理4、0-1标准化&#xff0c;所有解释变量5、绘制热…

计算机毕设 机器学习股票大数据量化分析与预测系统 - python 计算机毕设

文章目录 0 前言1 课题背景2 实现效果UI界面设计web预测界面RSRS选股界面 3 软件架构4 工具介绍Flask框架MySQL数据库LSTM 5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业…

【数据结构】树与二叉树(十六):二叉树的基础操作:插入结点(算法Insert)

文章目录 5.2.1 二叉树二叉树性质引理5.1&#xff1a;二叉树中层数为i的结点至多有 2 i 2^i 2i个&#xff0c;其中 i ≥ 0 i \geq 0 i≥0。引理5.2&#xff1a;高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点&#xff0c;其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

【计算机网络笔记】CIDR与路由聚合

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

nodejs+express重定向

前言&#xff1a; 本篇代码中需要安装的依赖包包括&#xff1a;request、express 1.常用重定向方法 nodejs中的重定向可以使用.redirect()方法&#xff0c;该方法中可以传两个参数&#xff1a;code和path&#xff0c;code指重定向时&#xff0c;当前访问的这个接口的返回码3…

20.2 设备树中的 platform 驱动编写

一、设备树下的 platform 驱动 platform 驱动框架分为总线、设备和驱动&#xff0c;总线不需要我们去管理&#xff0c;这个是 Linux 内核提供。在有了设备树的前提下&#xff0c;我们只需要实现 platform_driver 即可。 1. 修改 pinctrl-stm32.c 文件 先复习一下 pinctrl 子系…

C 语言多维数组

C 语言多维数组 在本教程中&#xff0c;您将借助示例学习使用多维数组&#xff08;二维和三维数组&#xff09;。 在C语言编程中&#xff0c;您可以创建一个数组数组。这些数组称为多维数组。例如&#xff0c; float x[3][4];这x是二维&#xff08;2d&#xff09;数组。该数…

14——1

这句话的意思是&#xff0c;如图中月份12天数23时&#xff0c;就是1223&#xff1b;当月份9天数2时&#xff0c;就是0902. 可以看到在上面给出的数组元素中&#xff0c;并没有连续挨在一起的2023数字元素——就有人可能输出答案0。 所以这里要看一下—— ——子序列的含义&…

网络运维Day16

文章目录 Docker简介什么是容器命名空间&#xff1a; Docker 的优缺点 Docker安装Docker镜像管理什么是镜像镜像管理 Docker容器管理运行容器容器启动、停止、重启拷贝文件进入容器容器与应用 DockerfileDockerfile 语法案例 总结 Docker简介 什么是容器 容器是用来装东西的&a…

诡异的bug之dlopen

序 本文给大家分享一个比较诡异的bug&#xff0c;是关于dlopen的&#xff0c;我大致罗列了我项目中使用代码方式及结构&#xff0c;更好的复现这个问题&#xff0c;也帮助大家进一步理解dlopen. 问题复现 以下是项目代码的文件结构&#xff1a; # tree . ├── file1 │ …

【大语言模型】Docker部署清华大学ChatGLM3教程

官方地址&#xff1a;https://github.com/THUDM/ChatGLM3 1 将代码保存至本地 方法1&#xff1a; git clone https://github.com/THUDM/ChatGLM3 方法2&#xff1a; https://github.com/THUDM/ChatGLM3/archive/refs/heads/main.zip 2 创建Docker文件 注&#xff1a;请先…

【分布式】CAP理论详解

一、CAP理论概述 在分布式系统中&#xff0c;CAP是指一组原则&#xff0c;它们描述了在网络分区&#xff08;Partition&#xff09;时&#xff0c;分布式系统能够提供的保证。CAP代表Consistency&#xff08;一致性&#xff09;、Availability&#xff08;可用性&#xff09;和…

CSS特效010:文字颜色渐变的流光效果

查看专栏目录 本专栏记录的是经常使用的CSS示例与技巧&#xff0c;主要包含CSS布局&#xff0c;CSS特效&#xff0c;CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点&#xff0c;CSS特效主要是一些动画示例&#xff0c;CSS花边是描述了一些CSS相关的库、…

Python编程-----网络通信

一.统一资源定位器URL 专为标识Internet网上资源位置而设的一种编址方式 ,URL一般由以下几个部分组成&#xff1a; 传输协议://主机IP地址(或域名地址)[:端口号]/资源所在路径和文件名 •传输协议是指访问该资源所使用的访问协议&#xff1b; •主机IP地址&#xff08;或域名…

C/C++轻量级并发TCP服务器框架Zinx-框架开发002: 定义通道抽象类

文章目录 2 类图设计3 时序图数据输入处理&#xff1a;输出数据处理总流程 4 主要实现的功能4.1 kernel类&#xff1a;基于epoll调度所有通道4.2 通道抽象类&#xff1a;4.3 标准输入通道子类4.4 标准输出通道子类4.5 kernel和通道类的调用 5 代码设计5.1 框架头文件5.2 框架实…

MATLAB中Filter Designer的使用以及XILINX Coefficient(.coe)File的导出

文章目录 Filter Designer的打开滤波器参数设置生成matlab代码生成XILINX Coefficient(.COE) File实际浮点数的导出官方使用教程 Filter Designer的打开 打开Filter Designer&#xff1a; 方法一&#xff1a;命令行中输入Filter Designer&#xff0c;再回车打开。 方法二&…