- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
日常开发中,树形结构的数据是比较常见的一种数据结构,比如系统菜单、组织机构、数据字典等,有时候需要后端把数据转成树形结构再返回给前端,对此特意封装通用树形结构工具类 。
封装了以下方法:
根据父id,递归获取所有子节点,转为树结构 。
。
根据子id,递归获取所有父节点,转为树结构 。
。
拼接 union sql脚本,根据查询查询条件、id字段名、pid字段名,拼接出sql 。
。
依赖hutool 。
<!-- hutool --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.18</version> </dependency>
。
package cn.huanzi.qch.util; import cn.hutool.core.bean.BeanUtil; import java.util.ArrayList; import java.util.Comparator; import java.util.List; /** * 树形结构工具类 */ public class TreeUtil{ /** * 根据父id,递归获取所有子节点,转为树结构 * * @param idFieldName id字段名称 * @param pIdFieldName pid字段名称 * @param childrenFieldName children字段名称 * @param pxFieldName px字段名称 * @param pId 父节点id * @param allList 所有菜单列表 * @return 每个根节点下,所有子菜单列表 */ public static <M> List<M> toTreeByParentId(String idFieldName, String pIdFieldName, String childrenFieldName, String pxFieldName,String pId, List<M> allList){ //子节点 List<M> childList = new ArrayList<>(allList.size()); for (int i = 0; i < allList.size(); i++) { M model = allList.get(i); //遍历所有节点将节点的父id与传过来的根节点的id比较 //父节点id字段,例如:pid if (BeanUtil.getFieldValue(model,pIdFieldName).equals(pId)){ childList.add(model); //删除,减少下次循环次数 allList.remove(i); i--; } } //递归 for (M model : childList) { //主键字段,例如:id,子节点字段,例如:children BeanUtil.setFieldValue(model,childrenFieldName,TreeUtil.toTreeByParentId(idFieldName,pIdFieldName,childrenFieldName,pxFieldName,String.valueOf(BeanUtil.getFieldValue(model,idFieldName)), allList)); } //排序字段,例如:px,如果不需要排序可以注释 if(null != pxFieldName && !pxFieldName.isEmpty()){ childList.sort(Comparator.comparingInt(m -> Integer.parseInt(String.valueOf(BeanUtil.getFieldValue(m, pxFieldName))))); //排序 } //底层节点的子节点赋空值,节省内存空间 if(childList.size() <= 0){ childList = null; } return childList; } public static <M> List<M> toTreeByParentId(String pId, List<M> allList){ //设置一下默认值 return TreeUtil.toTreeByParentId("id","pid","children","px",pId,allList); } /** * 根据子id,递归获取所有父节点,转为树结构 * * @param idFieldName id字段名称 * @param pIdFieldName pid字段名称 * @param childrenFieldName children字段名称 * @param cId 子节点id * @param allList 所有菜单列表 * @return 每个根节点下,所有子菜单列表 */ public static <M> M toTreeByChildrenId(String idFieldName, String pIdFieldName, String childrenFieldName,String cId, List<M> allList){ return TreeUtil.toTreeByChildrenId(idFieldName,pIdFieldName,childrenFieldName,null,cId,allList); } private static <M> M toTreeByChildrenId(String idFieldName, String pIdFieldName, String childrenFieldName,M parent,String cId, List<M> allList){ //父节点 M newParent = null; for (int i = 0; i < allList.size(); i++) { M model = allList.get(i); // 相等说明:找出当前节点 if (BeanUtil.getFieldValue(model,idFieldName).equals(cId)){ newParent = model; //设置子节点 if(parent != null){ ArrayList<M> childList = new ArrayList<>(1); childList.add(parent); BeanUtil.setFieldValue(newParent,childrenFieldName, childList); } //删除,减少下次循环次数 allList.remove(i); i--; break; } } //父节点为空,则说明为顶层节点 String menuParentId = newParent == null ? "" : String.valueOf(BeanUtil.getFieldValue(newParent,pIdFieldName)); if("".equals(menuParentId)){ return parent; } //父节点递归 newParent = TreeUtil.toTreeByChildrenId(idFieldName,pIdFieldName,childrenFieldName,newParent,menuParentId,allList); return newParent; } public static <M> M toTreeByChildrenId(String cId, List<M> allList){ //设置一下默认值 return TreeUtil.toTreeByChildrenId("id", "pid", "children",null,cId,allList); } /** * 拼接 union sql脚本,根据查询查询条件、id字段名、pid字段名,拼接出sql * @param select 查询字段,例如: select id * @param tableName 表名,例如 sys_dept * @param initWhere 查询条件,例如:pid = '-1' * @param idField id字段名 * @param pidField pid字段名 * @param maxLevel 拼接最大层级 * @return union拼接好的sql脚本 */ public static String getParentSql(String select, String tableName, String initWhere, String idField, String pidField, int maxLevel) { return getUnionSql(select,tableName,initWhere,idField,pidField,maxLevel); } public static String getChildSql(String select, String tableName, String initWhere, String idField, String pidField, int maxLevel) { return getUnionSql(select,tableName,initWhere,pidField,idField,maxLevel); } private static String getUnionSql(String select, String tableName, String initWhere, String whereIn, String selectIn, int maxLevel) { StringBuilder stringBuilder = new StringBuilder(select); stringBuilder.append(" from ").append(tableName).append(" where 1=1 "); if (null != initWhere && !initWhere.isEmpty()) { stringBuilder.append(" and ").append(initWhere); } String tmp = String.format("from %s where %s", tableName, initWhere); for(int i = 0; i < maxLevel; ++i) { tmp = String.format(" from %s where %s in ( select %s %s)", tableName, whereIn, selectIn, tmp); stringBuilder.append(" union ").append(select).append(tmp); } return stringBuilder.toString(); } }
。
/** * 测试 */ public static void main(String[] args) { ArrayList<Menu> list = new ArrayList<>(); list.add(new Menu("1","-1","系统管理",1)); list.add(new Menu("11","1","菜单维护",1)); list.add(new Menu("12","1","角色维护",2)); list.add(new Menu("13","1","系统安全",3)); list.add(new Menu("131","13","日志管理",1)); list.add(new Menu("12","-1","用户管理",2)); //备份list List<Menu> list1 = BeanUtil.copyToList(list, Menu.class); List<Menu> menus = TreeUtil.toTreeByParentId("-1", list); System.out.println(menus); Menu menu = TreeUtil.toTreeByChildrenId("131", list1); System.out.println(menu); String sql = TreeUtil.getChildSql("select id", "lp_sys_menu", "pid = '-1'", "id", "pid", 3); System.out.println(sql); } /** * 测试菜单类 */ public static class Menu { private String id; //节点id private String pid; //父节点id private List<Menu> children; //子节点 private int px; //排序字段 private String menuName; //菜单名称 public Menu() { } public Menu(String id, String pid, String name, int px) { this.id = id; this.pid = pid; this.menuName = name; this.px = px; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getPid() { return pid; } public void setPid(String pid) { this.pid = pid; } public List<Menu> getChildren() { return children; } public void setChildren(List<Menu> children) { this.children = children; } public int getPx() { return px; } public void setPx(int px) { this.px = px; } public String getMenuName() { return menuName; } public void setMenuName(String menuName) { this.menuName = menuName; } @Override public String toString() { return "Menu{" + "id='" + id + '\'' + ", pid='" + pid + '\'' + ", children=" + children + ", px=" + px + ", menuName='" + menuName + '\'' + '}'; } }
。
[Menu{id='1', pid='-1', children=[Menu{id='11', pid='1', children=null, px=1, menuName='菜单维护'}, Menu{id='12', pid='1', children=null, px=2, menuName='角色维护'}, Menu{id='13', pid='1', children=[Menu{id='131', pid='13', children=null, px=1, menuName='日志管理'}], px=3, menuName='系统安全'}], px=1, menuName='系统管理'}, Menu{id='12', pid='-1', children=null, px=2, menuName='用户管理'}] Menu{id='1', pid='-1', children=[Menu{id='13', pid='1', children=[Menu{id='131', pid='13', children=null, px=1, menuName='日志管理'}], px=3, menuName='系统安全'}], px=1, menuName='系统管理'} select id from lp_sys_menu where 1=1 and pid = '-1' union select id from lp_sys_menu where pid in ( select id from lp_sys_menu where pid = '-1') union select id from lp_sys_menu where pid in ( select id from lp_sys_menu where pid in ( select id from lp_sys_menu where pid = '-1')) union select id from lp_sys_menu where pid in ( select id from lp_sys_menu where pid in ( select id from lp_sys_menu where pid in ( select id from lp_sys_menu where pid = '-1')))
。
原数据 。
根据父id,递归获取所有子节点,转为树结构 。
根据子id,递归获取所有父节点,转为树结构 。
拼接 union sql脚本,根据查询查询条件、id字段名、pid字段名,拼接出sql 。
SELECT id FROM lp_sys_menu WHERE 1 = 1 AND pid = '-1' UNION SELECT id FROM lp_sys_menu WHERE pid IN ( SELECT id FROM lp_sys_menu WHERE pid = '-1' ) UNION SELECT id FROM lp_sys_menu WHERE pid IN ( SELECT id FROM lp_sys_menu WHERE pid IN ( SELECT id FROM lp_sys_menu WHERE pid = '-1' ) ) UNION SELECT id FROM lp_sys_menu WHERE pid IN ( SELECT id FROM lp_sys_menu WHERE pid IN ( SELECT id FROM lp_sys_menu WHERE pid IN ( SELECT id FROM lp_sys_menu WHERE pid = '-1' ) ) )
。
。
树形结构工具类暂时先记录到这,后续再进行补充 。
。
最后此篇关于树形结构工具类的文章就讲到这里了,如果你想了解更多关于树形结构工具类的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!