树形结构工具类

  前言

  日常开发中,树形结构的数据是比较常见的一种数据结构,比如系统菜单、组织机构、数据字典等,有时候需要后端把数据转成树形结构再返回给前端,对此特意封装通用树形结构工具类

  封装了以下方法:

  根据父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();     }  }

TreeUtil

 

  完整main测试

树形结构工具类

    /**      * 测试      */     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 + ''' +                     '}';         }      }

View Code

 

  效果展示

[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'                     )             )     )

 

 

  后记

  树形结构工具类暂时先记录到这,后续再进行补充

 

发表评论

相关文章