java树形递归结构实战

业务实战篇:java树形结构工具实战

前言

   嗨,大家好!辜负了大家的期望!多久才再次打开博客!这次打开,我会以技术结合业务为大家分享真正的干货。让大家真正的意义上将技术用到业务上,而不是纯粹的技术分享,或者业务演说。希望持续关注。后面会对spring 、mybatis、springboot、dubbo、springcloud、redis、mq、es等一系列的技术结合业务范畴进行展开,非常实用的工具和业务型通用技术简介。

回顾

 之前的 java树形结构工具,再次做下回顾,发现很多人私信我,联系不到我,不知道该如何使用该工具;我重新拿出来对该工具进行业务实战演练,希望帮助到将用到这个工具的伙伴们;

1)树形结构工具代码

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 描述:基层树形结构实体类--ID AND PARENTID AND CHILDSLIST
 * 作者: xfz
 * 时间:2016年7月2日
 * 版本号:1.0
 */
public class BaseTreeObj<E, ID extends Serializable> implements Serializable {
    private static final long serialVersionUID = 1L;
    private ID id;
    private ID parentId;
    private List<E> childsList = new ArrayList<E>();

    public void setId(ID id) {
        this.id = id;
    }

    public ID getId() {
        return id;
    }

    public ID getParentId() {
        return parentId;
    }

    public void setParentId(ID parentId) {
        this.parentId = parentId;
    }

    public List<E> getChildsList() {
        return childsList;
    }

    public void setChildsList(List<E> childsList) {
        this.childsList = childsList;
    }
}
在这里插入代码片
package com.asop.core.utils.tree;

import java.io.Serializable;
import java.util.List;

/**
 * 描述:树形结构服务类
 * 作者: xfz
 * 时间:2016年7月2日
 * 版本号:1.0
 */
public interface TreeInterface<T extends BaseTreeObj<T, ID>, ID extends Serializable> {
    /**
     * 获得指定节点下所有归档
     *
     * @param list
     * @param parentId
     * @return
     * @author xfz
     * 上午1:09:49
     */
    public List<T> getChildTreeObjects(List<T> list, ID parentId);

    /**
     * 递归列表
     *
     * @param list
     * @param t
     * @author xfz
     * 上午1:11:57
     */
    public void recursionFn(List<T> list, T t);

    /**
     * 获得指定节点下的所有子节点
     *
     * @param list
     * @param t
     * @return
     * @author xfz
     * 上午1:12:55
     */
    public List<T> getChildList(List<T> list, T t);

    /**
     * 判断是否还有下一个子节点
     *
     * @param list
     * @param t
     * @return
     * @author xfz
     * 上午1:13:43
     */
    public boolean hasChild(List<T> list, T t);
}

 
在这里插入代码片

package com.asop.core.utils.tree;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 描述:获得树形的服务实现 作者: xfz
 * <p>
 * 时间:2016年7月2日
 * <p>
 * 版本号:1.0
 */
public class TreeService<T extends BaseTreeObj<T, ID>, ID extends Serializable> implements
        TreeInterface<T, ID> {

    public List<T> getChildTreeObjects(List<T> list, ID parentId) {
        List<T> returnList = new ArrayList<T>();
        for (T res : list) {
            /**
             * 判断第一个对象是否为第一个节点
             *
             */
            if (((Comparable) res.getParentId()).compareTo(parentId) == 0) {
                /**
                 * 相等--说明第一个节点为父节点--递归下面的子节点
                 */
                recursionFn(list, res);
                returnList.add(res);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     * @author xfz
     * <p>
     * 上午1:11:57
     */
    public void recursionFn(List<T> list, T t) {
        List<T> childsList = getChildList(list, t);
        /**
         * 设置他的子集对象集
         */
        t.setChildsList(childsList);
        /**
         * 迭代--这些子集的对象--时候还有下一级的子级对象
         */
        for (T nextChild : childsList) {
            /**
             * 下一个对象,与所有的资源集进行判断
             */
            if (hasChild(list, nextChild)) {
                /**
                 * 有下一个子节点,递归
                 */
                Iterator<T> it = childsList.iterator();
                while (it.hasNext()) {
                    T node = it.next();
                    /**
                     * 所有的对象--跟当前这个childsList 的对象子节点
                     */
                    recursionFn(list, node);
                }
            }
        }
    }

    /**
     * 获得指定节点下的所有子节点
     *
     * @param list
     * @param t
     * @return
     * @author xfz
     * <p>
     * 上午1:12:55
     */
    public List<T> getChildList(List<T> list, T t) {
        List<T> childsList = new ArrayList<T>();
        for (T child : list) {
            /**
             * 判断集合的父ID是否等于上一级的id
             */
            if (((Comparable) child.getParentId()).compareTo(t.getId()) == 0) {
                childsList.add(child);
            }
        }
        return childsList;
    }

    /**
     * 判断是否还有下一个子节点
     *
     * @param list
     * @param t
     * @return
     * @author xfz
     * <p>
     * 上午1:13:43
     */
    public boolean hasChild(List<T> list, T t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }
}
 

老铁们喜欢静态工具,附上静态工具代码:


import com.asop.core.utils.tree.BaseTreeObj;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 描述:树形结构服务类
 * 作者: xfz
 * 时间:2016年7月2日
 * 版本号:1.0
 */
public class TreeUtil {
    /**
     * 获得指定节点下所有归档
     *
     * @param list
     * @param parentId
     * @return
     * @author xfz
     * 上午1:09:49
     */
    public static <T extends BaseTreeObj<T, ID>, ID extends Serializable> List<T> getChildTreeObjects(List<T> list, ID parentId) {
        List<T> returnList = new ArrayList<T>();
        for (T res : list) {
            /**
             * 判断第一个对象是否为第一个节点
             *
             */
            if (((Comparable) res.getParentId()).compareTo(parentId) == 0) {
                /**
                 * 相等--说明第一个节点为父节点--递归下面的子节点
                 */
                recursionFn(list, res);
                returnList.add(res);
            }
        }
        return returnList; 
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     * @author xfz
     * 上午1:11:57
     */
    public static <T extends BaseTreeObj<T, ID>, ID extends Serializable> void recursionFn(List<T> list, T t) {
        List<T> childsList = getChildList(list, t);
        /**
         * 设置他的子集对象集
         */
        t.setChildsList(childsList);
        /**
         * 迭代--这些子集的对象--时候还有下一级的子级对象
         */
        for (T nextChild : childsList) {
            /**
             * 下一个对象,与所有的资源集进行判断
             */
            if (hasChild(list, nextChild)) {
                /**
                 * 有下一个子节点,递归
                 */
                Iterator<T> it = childsList.iterator();
                while (it.hasNext()) {
                    T node = it.next();
                    /**
                     * 所有的对象--跟当前这个childsList 的对象子节点
                     */
                    recursionFn(list, node);
                }
            }
        }
    }

    /**
     * 获得指定节点下的所有子节点
     *
     * @param list
     * @param t
     * @return
     * @author xfz
     * 上午1:12:55
     */
    public static <T extends BaseTreeObj<T, ID>, ID extends Serializable> List<T> getChildList(List<T> list, T t) {
        List<T> childsList = new ArrayList<T>();
        for (T child : list) {
            /**
             * 判断集合的父ID是否等于上一级的id
             */
            if (((Comparable) child.getParentId()).compareTo(t.getId()) == 0) {
                childsList.add(child);
            }
        }
        return childsList;
    }

    /**
     * 判断是否还有下一个子节点
     *
     * @param list
     * @param t
     * @return
     * @author xfz
     * 上午1:13:43
     */
    public static <T extends BaseTreeObj<T, ID>, ID extends Serializable> boolean hasChild(List<T> list, T t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }
}
 

树形结构场景应用

   在实际应用中,我们很多项目很多业务模块经常用到树形结构呈现;经常出现在:结构关系中是父子级关系;如:表结构、前端页面父子级标签等等;

   今天我们主要讲解关于结构,父子级关系的应用场景;

    我想很多人经常用到表结构有父子级别的关系,经常需要递归遍历他们之间的关系处理。例如:机构表(含id,parentId)、菜单表(含id,parentId)或者说是机构表(含code、parentCode)等业务需要的递归关系;

   只要是父子级关系应用,我们都常会有需求:

1)获取树形结构列表;
2)指定某个节点获取该节点下的列表(要求组装成树形列表返回不含当前节点);
3)指定某个节点获取含该节点下的列表(要求组装成树形列表返回);
4)指定某个节点获取该节点下的列表;
5)校验某个节点下是否还有子节点;
只要有以上的需求,我们的工具就能发挥到实际的应用。那我们该怎么实现呢??下面请看,树形结构实战段落…

树形结构实战

 假设我们有一个菜单表 如下:

CREATE TABLE `sys_menu` (
  `id` bigint(20) NOT NULL,
  `tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
  `del_flag` varchar(4) DEFAULT '0' COMMENT '删除标识(0-正常,1-删除) 默认0',
  `sort` tinyint(4) DEFAULT '0' COMMENT '排序(升序)默认0',
  `create_user` varchar(50) DEFAULT NULL COMMENT '创建用户',
  `update_user` varchar(50) DEFAULT NULL COMMENT '修改用户',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `remarks` varchar(250) DEFAULT NULL COMMENT '备注',
  `app_id` bigint(20) DEFAULT NULL COMMENT '应用ID',
  `parent_id` bigint(20) DEFAULT '0' COMMENT '父菜单ID,一级菜单为0',
  `name` varchar(50) CHARACTER SET utf8 DEFAULT NULL COMMENT '菜单名称',
  `code` varchar(50) NOT NULL COMMENT '菜单编号',
  `route_url` varchar(200) DEFAULT NULL COMMENT '后端URL',
  `view_url` varchar(200) DEFAULT NULL COMMENT '前端菜单URL',
  `permission` varchar(500) DEFAULT NULL COMMENT '菜单权限标识(多个用逗号分隔,如:user:list,user:create)',
  `type` int(11) NOT NULL COMMENT '类型   0:目录   1:菜单   2:按钮',
  `icon` varchar(50) DEFAULT NULL COMMENT '菜单图标',
  `status` tinyint(4) DEFAULT '1' COMMENT '状态  0:禁用   1:正常, 默认1',
  PRIMARY KEY (`id`),
  UNIQUE KEY `code` (`code`),
  KEY `parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='菜单表';
   继承BaseTreeObj实现菜单树类(该类是为了展示给前端呈现的VO):
package com.asop.system.pojo.vo;

import com.asop.core.utils.tree.BaseTreeObj;

/**
 * 菜单树形
 */
public class MenuTree extends BaseTreeObj<MenuTree, Long> {
    /**
     * 代码
     */
    private String code;
    /**
     * 名称
     */
    private String name;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
   这边省略大家各自实现的domain层、dao层、service层。。。。。。。。。。

1)获取树形结构列表;

  /**
     * 获取菜单树形列表
     */
    @Test
    public void testFindMenuTree() {
        /**
         * 1.获取所有的菜单列表[一般做了缓存获取等]
         */
        List<MenuTree> menuTrees = new ArrayList<>();
        List<SysMenu> menuList = sysMenuService.selectList(null);
        convertMenuList(menuTrees, menuList);
        /**
         * 2.组装树形结构
         */
        TreeInterface<MenuTree, Long> menuTreeService = new TreeService<>();
        List<MenuTree> treeList = menuTreeService.getChildTreeObjects(menuTrees, 0L);
        System.out.println(JSON.toJSONString(treeList));
    }

2)指定某个节点获取该节点下的列表(要求组装成树形列表返回不含当前节点)

/**
     * 获取指定某个节点下的所有菜单树形列表
     */
    @Test
    public void testFindMenuTreeByOne() {
        /**
         * 1.获取所有的菜单列表[一般做了缓存获取等]
         */
        List<MenuTree> menuTrees = new ArrayList<>();
        List<SysMenu> menuList = sysMenuService.selectList(null);
        convertMenuList(menuTrees, menuList);
        TreeInterface<MenuTree, Long> menuTreeService = new TreeService<>();
        /**
         * 2.指定某个节点,获取这个节点下的树形列表
         */
        SysMenu res = sysMenuService.selectById(1L);
        MenuTree menuTree = new MenuTree();
        convertMenu(res, menuTree);
        /**
         * 3.组装树形结构
         */
        List<MenuTree> treeList = menuTreeService.getChildTreeObjects(menuTrees, res.getId());
        System.out.println(JSON.toJSONString(treeList));
    }
 

3)指定某个节点获取含该节点下的列表(要求组装成树形列表返回)

  /**
     * 获取指定某个节点下的所有菜单树形列表
     */
    @Test
    public void testFindMenuTreeByOneIncludeOne() {
        /**
         * 1.获取所有的菜单列表[一般做了缓存获取等]
         */
        List<MenuTree> menuTrees = new ArrayList<>();
        List<SysMenu> menuList = sysMenuService.selectList(null);
        convertMenuList(menuTrees, menuList);
        TreeInterface<MenuTree, Long> menuTreeService = new TreeService<>();
        /**
         * 2.指定某个节点,获取这个节点下的树形列表
         */
        SysMenu res = sysMenuService.selectById(1L);
        MenuTree menuTree = new MenuTree();
        convertMenu(res, menuTree);
        /**
         * 3.组装树形结构
         */
        List<MenuTree> treeList = menuTreeService.getChildTreeObjects(menuTrees, res.getId());
        /**
         * 4.设置某个节点下的所有子节点
         */

        menuTree.setChildsList(treeList);
        System.out.println(JSON.toJSONString(menuTree));
    }

4)指定某个节点获取该节点下的列表

/**
     * 获取指定菜单某个节点下的子节点
     */
    @Test
    public void testFindMenuChildByOne() {
        /**
         * 1.获取所有的菜单列表[一般做了缓存获取等]
         */
        List<MenuTree> menuTrees = new ArrayList<>();
        List<SysMenu> menuList = sysMenuService.selectList(null);
        convertMenuList(menuTrees, menuList);
        TreeInterface<MenuTree, Long> menuTreeService = new TreeService<>();
        /**
         * 2.指定某个节点,获取这个节点下的树形列表
         */
        SysMenu res = sysMenuService.selectById(1L);
        MenuTree menuTree = new MenuTree();
        convertMenu(res, menuTree);
        /**
         * 3.组装树形结构
         */
        List<MenuTree> treeList = menuTreeService.getChildList(menuTrees, menuTree);
        System.out.println(JSON.toJSONString(treeList));
    }
 

总结

     树形结构工具,就是这么简单方便使用,想替换成静态工具的老铁们,可以直接使用上述直接替换业务代码中的实现部分;

       好了,今天的分享就到这,敬请期待明天的技术篇章分享,帮助到你的记得点个赞,加入收藏!后面持续干货分享!!感谢老铁的阅读。。。。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值