Java将List转换为Tree数据

思路

  1. 我们首先要知道数据中,哪两列能够体现父子级
  2. 我们需要找到最顶层父 id 是什么,因为只有知道最顶层的父 id,我们才能进行递归
  3. 我们要在不改变数据的原有结构下,而转换为 Tree 结构,那么就需要创建新的结构

代码

/*** Date: 2023/10/28* Author: PuKun* Description: 树形数据ID*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TreeId {}
/*** Date: 2023/10/28* Author: PuKun* Description: 树形数据的父类id*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TreeParentId {}
/*** Date: 2023/10/28* Author: PuKun* Description: Tree工具类*/
public class TreeUtils<T> {private Class<T> aClass;private Field treeIdField;private Field treeParentIdField;private final String CHILDREN_KEY = "children";public TreeUtils(Class<T> aClass) {if (aClass == null) {throw new RuntimeException("传入的class为NULL");}this.aClass = aClass;init();}private void init() {Field[] fields = this.aClass.getDeclaredFields();for (Field f : fields) {if (f.isAnnotationPresent(TreeId.class)) {this.treeIdField = f;} else if (f.isAnnotationPresent(TreeParentId.class)) {this.treeParentIdField = f;}// 这一步也没什么用,我的想法是如果这两列提前找到,那么就提前结束循环if (this.treeIdField != null && this.treeParentIdField != null) {break;}}if (this.treeIdField == null || this.treeParentIdField == null) {throw new RuntimeException("没有找到相应的注解");}// 避免因字段为private时,无法访问this.treeIdField.setAccessible(true);this.treeParentIdField.setAccessible(true);}public List<HashMap<String, Object>> getTreeData(List<T> data) throws IllegalAccessException {Object topParentId = getTopParentId(data);return buildTreeData(data, topParentId);}private Object getTopParentId(List<T> data) throws IllegalAccessException {// 获取所有parentId的值Map<Object, Integer> parentIdMap = new HashMap<>();for (T o : data) {Object v = this.treeParentIdField.get(o);parentIdMap.put(v, 0);}// 计算每个parentId的数量for (T o : data) {Object v = this.treeIdField.get(o);if (parentIdMap.containsKey(v)) {int keyValue = parentIdMap.get(v);parentIdMap.put(v, ++keyValue);}}// 当parentId的数量等于0时,说明当前的parentId没有找到对应的treeId,那么就是最顶层的parentIdObject topParentId = null;Set<Map.Entry<Object, Integer>> entries = parentIdMap.entrySet();for (Map.Entry<Object, Integer> e : entries) {if (e.getValue() == 0) {topParentId = e.getKey();}}return topParentId;}private List<HashMap<String, Object>> buildTreeData(List<T> data, Object parentId) throws IllegalAccessException {List<HashMap<String, Object>> list = new ArrayList<>();for (T o : data) {Object pid = this.treeParentIdField.get(o);Object tid = this.treeIdField.get(o);if (pid.equals(parentId)) {HashMap<String, Object> map = new HashMap<>();Field[] fields = this.aClass.getDeclaredFields();for (Field f : fields) {f.setAccessible(true);map.put(f.getName(), f.get(o));}List<HashMap<String, Object>> children = buildTreeData(data, tid);if (children.size() > 0) {map.put(CHILDREN_KEY, children);}list.add(map);}}return list;}
}
/*** Date: 2023/11/14* Author: PuKun* Description: 树形工具类测试*/
class TreeUtilsTest {class Dept {@TreeIdprivate int id;private String deptName;@TreeParentIdprivate int parentId;public Dept(int id, String deptName, int parentId) {this.id = id;this.deptName = deptName;this.parentId = parentId;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getDeptName() {return deptName;}public void setDeptName(String deptName) {this.deptName = deptName;}public int getParentId() {return parentId;}public void setParentId(int parentId) {this.parentId = parentId;}}class Dept2 {@TreeIdprivate String id;private String deptName;@TreeParentIdprivate String parentId;public Dept2(String id, String deptName, String parentId) {this.id = id;this.deptName = deptName;this.parentId = parentId;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getDeptName() {return deptName;}public void setDeptName(String deptName) {this.deptName = deptName;}public String getParentId() {return parentId;}public void setParentId(String parentId) {this.parentId = parentId;}}@Testvoid getTreeData() {// List<Dept> list = new ArrayList<>();
//        list.add(new Dept(1, "闲简居有限公司", 0));
//        list.add(new Dept(2, "开发部", 1));
//        list.add(new Dept(4, "Java组", 2));
//        list.add(new Dept(5, "前端组", 2));
//        list.add(new Dept(3, "测试部", 1));//        list.add(new Dept(2, "开发部", 1));
//        list.add(new Dept(4, "Java组", 2));
//        list.add(new Dept(5, "前端组", 2));
//        list.add(new Dept(3, "测试部", 1));//        TreeUtils<Dept> treeUtils = new TreeUtils<>(Dept.class);
//        List<HashMap<String, Object>> mapList = null;
//        try {
//            mapList = treeUtils.getTreeData(list);
//        } catch (IllegalAccessException e) {
//            Assertions.fail(e.getMessage());
//        }List<Dept2> list = new ArrayList<>();list.add(new Dept2("1", "闲简居有限公司", "0"));list.add(new Dept2("2", "开发部", "1"));list.add(new Dept2("4", "Java组", "2"));list.add(new Dept2("5", "前端组", "2"));list.add(new Dept2("3", "测试部", "1"));TreeUtils<Dept2> treeUtils = new TreeUtils<>(Dept2.class);List<HashMap<String, Object>> mapList = null;try {mapList = treeUtils.getTreeData(list);} catch (IllegalAccessException e) {Assertions.fail(e.getMessage());}Assertions.assertNotEquals(null, mapList);System.out.println(mapList);}
}

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

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

相关文章

【活动通知】2023 Elastic Meetup 北京站将于12月2日下午1点30在北京召开

《2023 Elastic Meetup 北京站》活动将于 12 月 2 日下午 1 点 30 在北京市海淀区西北旺东路10号腾讯北京总部大楼213会议室举办&#xff0c;届时将有行业专家及知名企业分享他们在 Elasticsearch 应用中的经验与观点&#xff0c;带来最前沿的技术分享与思想碰撞。 请使用电脑浏…

C++标准模板库(STL)-set介绍

在C中&#xff0c;set是一种容器&#xff0c;它包含了唯一元素的有序集合。set库提供了一系列的类模板&#xff0c;用于创建和操作集合。 set基本操作 insert()&#xff1a;此操作用于将元素插入到set中。调用insert()函数&#xff0c;并传入需要插入的元素即可。例如&#x…

车载毫米波雷达行业发展5——企业

5.1 博世 5.1.1 公司简介 博世集团创立于 1886 年&#xff0c;业务涵盖汽车与智能交通技术、工业技术、消费品、能源与建 筑技术四大领域&#xff0c;是德国最大的工业企业之一、全球最大的汽车零部件供应商、最早研究车载毫米波雷达的企业之一。博世在高级辅助驾驶和自动驾驶…

移动语义和完美转发

移动语义和完美转发 移动语义 移动语义是 C11 引入的一项特性&#xff0c;通过右值引用&#xff08;Rvalue Reference&#xff09;实现。它的目标是提高对于临时对象或即将销毁的对象的效率&#xff0c;避免不必要的深拷贝&#xff0c;而是在必要的时候将资源所有权从一个对象…

B Label, BL Label 指令

B Label, BL Label 跳转到标号Label 处&#xff0c;B跳转指令的跳转范围大小为[0,32MB], 可以往前跳&#xff0c;也可以往后条&#xff0c;无条件跳转指令B主要用在循环&#xff0c;分之结构的汇编程序中&#xff0c;使用示例如下。 CMP R2, #0 REQ label 若R2 0,则跳转到labe…

mfc140u.dll丢失的解决方法,以及mfc140u.dll解决方法的优缺点

在使用电脑过程中&#xff0c;有时会遇到一些与动态链接库文件&#xff08;DLL&#xff09;相关的错误。其中&#xff0c;mfc140u.dll丢失的错误是较为常见的一种。当这个关键的mfc140u.dll文件丢失或损坏时&#xff0c;可能会导致某些应用程序无法正常运行。在本文中&#xff…

linux清理僵尸进程

当你top看到这个&#xff0c;或者按M后看到内存吃的很多&#xff0c;那你看下有没有&#x1f9df; 二选一查看是什么进程 ps aux | egrep "Z|defunct" ps -aux | awk {if($8"Z"){print $2,$11}}没用直接杀杀杀 kill -9 查到的PID号可中断下载文件 wget…

AlmaLinux download

前言 一个开源的、社区拥有和管理的、永远免费的企业级Linux发行版&#xff0c;专注于长期稳定性&#xff0c;提供一个健壮的生产级平台。AlmaLinux操作系统是1:1二进制兼容RHEL和pre-Stream CentOS。 AlmaLinux download VersionAlmaLinux downloadAlmaLinux backup阿里云…

webshell免杀之传参方式

1.Cookie 由于Cookie基本上是每个web应用都需要使用到的&#xff0c;php应用在默认情况下&#xff0c;在Cookies请求头中会存在一个PHPSESSIDxxxx这样的cookie&#xff0c;其实这个就可以成为我们的传参位置 使用burp抓包将内容改成base64加密后的命令 可以看到已经执行成功了…

BeautifulReport测试报告框架

BeautifulReport测试报告框架 ##执行文件excute_case.py import unittest import os, datetime from BeautifulReport import BeautifulReportroot_dir os.path.dirname(os.path.abspath(__file__)).replace(\\, /) print(root_dir路径,root_dir) #test_dir root_dir /test…

c语言从入门到实战——回调函数与qsort的讲解和模拟实现

回调函数与qsort的讲解和模拟实现 前言1. 回调函数是什么&#xff1f;2. qsort2.1 使用qsort函数排序整型数据2.2 使用qsort排序结构数据 3. qsort函数的模拟实现 前言 回调函数是一个函数&#xff0c;它作为参数传递给另一个函数&#xff0c;并且能够在该函数内部被调用。在C…

Nginx 可视化管理平台:nginx-proxy-manager

本心、输入输出、结果 文章目录 Nginx 可视化管理平台:nginx-proxy-manager前言nginx-proxy-managernginx-proxy-manager 特性快速开始使用 Docker 网络开启 Docker 健康检查相关可视化页面相关链接弘扬爱国精神Nginx 可视化管理平台:nginx-proxy-manager 编辑:简简单单 Onl…

Vue 路由器传参和取值 路径参数

Query参数取值 http://www.csdn/index?id10&age123 取值 this.$route.query.id//获取id值 this.$route.query.age//获取age值传值 <router-link :to"{path:/index,query:{ id:10,age:123 }}"></router-link>携带参数跳转到指定路由 this.$ro…

深入解析SSD Wear Leveling磨损均衡技术:如何让你的硬盘更长寿?

SSD的存储介质是什么&#xff0c;它就是NAND闪存。那你知道NAND闪存是怎么工作的吗&#xff1f;其实&#xff0c;它就是由很多个晶体管组成的。这些晶体管里面存储着电荷&#xff0c;代表着我们的二进制数据&#xff0c;要么是“0”&#xff0c;要么是“1”。NAND闪存原理上是一…

【DevOps】Git 图文详解(五):远程仓库

Git 图文详解&#xff08;五&#xff09;&#xff1a;远程仓库 1.远程用户登录1.1 &#x1f511; 远程用户登录&#xff1a;HTTS1.2 &#x1f511; 远程用户登录&#xff1a;SSH 2.远程仓库指令 &#x1f525;3.推送 push / 拉取 pull4.fetch 与 pull 有什么不同 &#xff1f; …

【汇编】“转移”综述、操作符offset、jmp指令

文章目录 前言一、转移综述1.1 :背景&#xff1a;1.2 转移指令1.3 转移指令的分类按转移行为根据指令对IP修改的范围不同 二、操作符offset2.1 offset操作符是干什么的&#xff1f;标号是什么&#xff1f; 2.2 nop是什么&#xff1f; 三、jmp指令3.1 jmp指令的功能3.2 jmp指令&…

【目标测距】雷达投影测距

文章目录 前言一、读取点云二、点云投影图片三、读取检测信息四、点云投影测距五、学习交流 前言 雷达点云投影相机。图片目标检测&#xff0c;通过检测框约束等等对目标赋予距离。计算消耗较大&#xff0c;适合离线验证操作。在线操作可以只投影雷达检测框。 一、读取点云 py…

关于node安装和nvm安装的问题

node 1.已经自定义路径安装了node&#xff0c;但是在cmd输入node -v显示不是内部命令 路径问题&#xff1a;确保 Node.js 已经被添加到了系统的环境变量 PATH 中。PATH 环境变量包含了操作系统用来查找命令的位置。你可以通过以下步骤检查 Node.js 是否已被添加到 PATH&#x…

校园报修抢修小程序系统开发 物业小区报修预约上门维修工单系统

开发的功能模块有&#xff1a; 1.报修工单提交&#xff1a;学生、教职员工等可以使用小程序提交报修请求。这通常包括选择报修的问题类型&#xff08;如水漏、电器故障、照明问题等&#xff09;&#xff0c;地点&#xff0c;报修联系人&#xff0c;联系电话等&#xff0c;并提供…

【5k字长文 | Vue学习笔记】#1 认识Vue对象和基础语法

Vue是一个非常流行的渐进式JavaScript框架&#xff0c;渐进式指的是自底向上&#xff0c;从小组件逐渐向上构成整个项目&#xff0c;渐进式还可以理解为&#xff1a;用什么就拿什么&#xff0c;每个组件只做自己的事&#xff0c;尽可能解耦合。 本节我们将学习简单的Vue实例&a…