有关自连接表的统一封装

news2024/10/6 0:08:28

表结构

在这里插入图片描述

RecursionBean

@Getter
@Setter
@ToString
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class RecursionBean<T>  extends BaseVO {
    /**
     * 编号
     */
    private T id;

    /**
     * 父权限ID,根节点的父权限为空
     * 注释掉@JsonIgnore,是为了前端判断是否是顶级节点,顶级节点才能添加子节点
     */
//    @JsonIgnore
    private T pid;

    private List<? extends RecursionBean<T>> children;

}

封装从服务器端返回的树形数据:RecursionItem

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class RecursionItem<T> extends RecursionBean<T> {

    /**
     * 名称
     */
    private String name;

    public RecursionItem(T id, String name) {
        super.setId(id);
        this.name = name;
    }

    public RecursionItem(T id, String name, List<? extends RecursionBean<T>> children) {
        super.setId(id);
        this.name = name;
        super.setChildren(children);
    }
}

工具类

public class RecursionBeanUtil {
    /**
     * 递归查询子节点
     *
     * @param root 根节点
     * @param list 所有节点
     * @return 根节点信息
     */
    private static <E, T extends RecursionBean<E>> List<T> getChildren(T root, List<T> list) {
        final List<T> res = new ArrayList<>();
        for (T item : list) {
            if (Objects.equals(item.getPid(), root.getId())) {
                item.setChildren(getChildren(item, list));
                res.add(item);
            }
        }
        return res;
    }


    public static <E, T extends RecursionBean<E>> List<T> getRecursionList(List<T> list) {
        if (CollectionUtil.isEmpty(list)) {
            return list;
        }

        // 所有的节点
        final List<E> allList = list.stream()
                .map(T::getId)
                .toList();

        // 顶级节点(父ID为空)
        final List<E> topList = list.stream()
                .filter(item -> item.getPid() == null)
                .map(T::getId)
                .toList();

        // 父级节点(不包含在已有父级列表中的新PID)
        final List<E> parentList = list.stream()
                .map(T::getPid)
                .filter(itemPid -> !topList.contains(itemPid))
                .distinct()
                .toList();

        // 叶子节点(非顶级且不在父级列表中的节点ID)
        final List<E> leafList = allList.stream()
                .filter(id -> !topList.contains(id))
                .filter(id -> !parentList.contains(id))
                .toList();

        final List<T> res = new ArrayList<>();
        boolean topFlag = true;
        // 如果待处理集合中顶级节点
        for (T item : list) {
            if (item.getPid() == null) {
                topFlag = false;
                item.setChildren(getChildren(item, list));
                res.add(item);
            }
        }
        if (!topFlag) {
            return res;
        }
        boolean parentFlag = true;
        //如果待处理集合中没有顶级节点但有父节点
        for (T item : list) {
            // 是父节点但不是叶子节点
            if (parentList.contains(item.getPid()) && !leafList.contains(item.getId())) {
                item.setChildren(getChildren(item, list));
                parentFlag = false;
                res.add(item);
            }
        }
        if (!parentFlag) {
            return res;
        }
        //如果待处理集合中全部是叶子节点
        for (T item : list) {
            // 是父节点但不是叶子节点
            if (leafList.contains(item.getId())) {
                item.setChildren(getChildren(item, list));
                res.add(item);
            }
        }
        return res;
    }
}

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

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

相关文章

Linux驱动开发常用调试方法汇总

引言&#xff1a;在 Linux 驱动开发中&#xff0c;调试是一个至关重要的环节。开发者需要了解多种调试方法&#xff0c;以便能够快速定位和解决问题。 1.利用printk 描述&#xff1a; printk 是 Linux 内核中的一个调试输出函数&#xff0c;类似于用户空间中的 printf。它用于…

CE找CSGO人物坐标和视角基址-幽络源原创

前言 幽络源站长本次免费分享的是CE找CSGO人物坐标和视角基址 本教程分为两篇&#xff0c;当前为上篇->找基址 所具备的知识 CE的使用 教程目的 通过CE找到一些基地址&#xff0c;然后结合Python实现CSGO的透视绘制&#xff0c;这里我们是纯手写透视。 第一步&#x…

如何使用CMD命令启动应用程序(二)

说明&#xff1a;去年1024发布了一篇博客&#xff0c;介绍如何使用CMD命令启动应用程序&#xff0c;但实际情况&#xff0c;有些程序可能无法用配置环境变量的方式来启动&#xff0c;本文针对两种情况下的程序&#xff0c;如何使用CMD命令来启动&#xff0c;算是对上一篇博客的…

Java开发必知必会的一些工具

本文主要介绍 Java 程序员应该学习的一些基本和高级工具。 如果你想成为一名更好的程序员&#xff0c;最重要的技巧之一就是学习你的编程工具。 Java 世界中存在着如此多的工具&#xff0c;从 Eclipse、NetBeans 和 IntelliJ IDEA 等著名的 IDE 到 JConsole、VisualVM、Eclipse…

class 004 选择 冒泡 插入排序

我感觉这个真是没有什么好讲的, 这个是比较简单的, 感觉没有什么必要写一篇博客, 而且这个这么简单的排序问题肯定有人已经有写好的帖子了, 肯定写的比我好, 所以我推荐大家直接去看“左程云”老师的讲解就很好了, 一定是能看懂的, 要是用文字形式再写一遍, 反而有点画蛇添足了…

计算机视觉算法知识详解(含代码示例)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

算法: 二分查找题目练习

文章目录 二分查找二分查找在排序数组中查找元素的第一个和最后一个位置搜索插入位置x 的平方根山脉数组的峰顶索引寻找峰值寻找旋转排序数组中的最小值点名 总结精华模版 二分查找 二分查找 没啥可说的,轻轻松松~ class Solution {public int search(int[] nums, int target…

IDEA 配置 Git 详解

本文将介绍在IntelliJ IDEA 中如何配置Git 没有安装配置 Git 的可以参考我的这篇文章&#xff1a;安装配置 Git 一、操作环境及准备 1.win 10 2.已安装且配置了Git 3.有Gitee账户 4.安装了IntelliJ IDEA 2023.2.1 5.全程联网 二、配置步骤 2.1 配置git 1.采用全局设置&…

Pragmatic Task务实任务——指导语义通信的优化

1. 语义通信 语义通信&#xff08;Semantic Communication&#xff09;的核心理念是传递不仅仅是数据本身&#xff0c;而是数据所包含的“语义”或“意义”。这与传统通信系统不同&#xff0c;传统系统只注重如何准确、高效地传输数据&#xff0c;而语义通信则要求传输的信息能…

基于Pcap4j收发自定义协议报文(注意事项/踩坑总结)

大致内容&#xff1a;完善自定义的Cat21协议&#xff0c;补充至少5个数据类型不同的协议字段 用户输入Cat21协议字段&#xff0c;发送数据包 用户捕获Cat21数据包&#xff0c;打印输出字段值 本篇博客是直接将自定义协议报文封装在MAC帧的payload中的。 一、Cat21Packet类 1…

拓扑排序简介

拓扑排序(Topological Sort)是一种重要的图算法,用于对有向无环图(DAG, Directed Acyclic Graph)中的节点进行排序。拓扑排序的结果是一种线性序列,使得对于图中的任意一条有向边(u, v),顶点u都在顶点v之前。这种排序常用于任务调度、编译器依赖关系分析等领域。 拓…

算法题总结(八)——字符串

531、反转字符串二 给定一个字符串 s 和一个整数 k&#xff0c;从字符串开头算起&#xff0c;每计数至 2k 个字符&#xff0c;就反转这 2k 字符中的前 k 个字符。 如果剩余字符少于 k 个&#xff0c;则将剩余字符全部反转。如果剩余字符小于 2k 但大于或等于 k 个&#xff0c…

VTK有向包围盒

文章目录 一、vtkOBBTree1.1 几种树结构的对比1.2 获取线段与数据集的交点1.3 OBB树可视化1.4 对齐两个数据集1.5 圆柱形有向包围盒 本文的主要内容&#xff1a;简单介绍VTK中有向包围盒的相关功能。 主要涉及vtkOBBTree类。 哪些人适合阅读本文&#xff1a;有一定VTK基础的人。…

python全栈开发是什么?

全栈指掌握多种技能&#xff0c;并能利用多种技能独立完成产品。通俗的说就是与这项技能有关的都会&#xff0c;都能独立完成。 python&#xff0c;因为目前很火&#xff0c;能开发的项目很多。例如&#xff1a;web前端后端&#xff0c;自动化运维&#xff0c;软件、小型游戏开…

基于ssm的二手手机商城的设计与实现

文未可获取一份本项目的java源码和数据库参考。 题目简介&#xff1a; 随着时代的发展与科技的进步&#xff0c;人们的物质生活水平越来愈高&#xff0c;对智能化电子产品的需求也越来越高&#xff0c;手机就是一个很好的表现。近年来&#xff0c;随着华为、小米、vivo、ipho…

问题-python-运行报错-SyntaxError: Non-UTF-8 code starting with ‘\xd5‘ in file 汉字编码问题

​ 编码: 把字符转换成字节序列的过程。因为计算机只能处 理二进制数据&#xff0c;所以不能直接处理文本&#xff0c;需要先把文本转换为二进制数据。 解码: 把二进制数据转换成字符的过程。把接收到的数据转换成程序中使用的编码方式。 ​ 这个报错原因就是编码和解码没达成…

地理定位营销与开源AI智能名片O2O商城小程序的融合与发展

摘要&#xff1a;本文阐述地理定位营销的概念、手段及其在商业中的应用&#xff0c;探讨开源AI智能名片O2O商城小程序如何与地理定位营销相结合&#xff0c;为企业营销带来新的机遇与挑战。 一、引言 在当今数字化营销的时代&#xff0c;地理定位营销已成为一种重要的营销手段…

【C语言】分支与循环

文章目录 前言if语句关系操作符逻辑操作符&#xff1a;&& , || , &#xff01;switch语句if语句和switch语句的对比 while循环for循环do-while循环break和continue语句循环嵌套goto语句 前言 C语⾔是结构化的程序设计语⾔&#xff0c;这⾥的结构指的是顺序结构、选择&…

【GeekBand】C++设计模式笔记5_Observer_观察者模式

1. “组件协作”模式 现代软件专业分工之后的第一个结果是“框架与应用程序的划分”&#xff0c;“组件协作”模式通过晚期绑定&#xff0c;来实现框架与应用程序之间的松耦合&#xff0c;是二者之间协作时常用的模式。典型模式 Template MethodStrategyObserver / Event 2.…

D28【python 接口自动化学习】- python基础之输入输出与文件操作

day28 输入 学习日期&#xff1a;20241005 学习目标&#xff1a;输入输出与文件操作&#xfe63;-40 输入&#xff1a;如何接收用户通过键盘输入的数据&#xff1f; 学习笔记&#xff1a; 输入设备与输入方式 Input函数 命令行参数 可选参数 必填参数 强制转换参数类型 总…