JAVA 递归实现树形

转载:Java中树形菜单的实现方式(超全详解!)-CSDN博客

第一种写法:

建菜单对象PermissionDirectory

@Data
public class PermissionDirectory {
 
    @MyAnnotation("主键id")
    private int id;
 
    @MyAnnotation("父目录id")
    private int parentId;
 
    @MyAnnotation("菜单名称")
    private String menuName;
 
    @MyAnnotation("菜单等级")
    private int menuLevel;
 
    @MyAnnotation("路由")
    private String route;
}
 

创建存储菜单对象PermissionDirectoryResVO

@Data
public class PermissionDirectoryResVO {
 
    @MyAnnotation("主键id")
    private Integer id;
 
    @MyAnnotation("父目录id")
    private Integer parentId;
 
    @MyAnnotation("菜单名称")
    private String menuName;
 
    @MyAnnotation("菜单等级")
    private Integer menuLevel;
 
    @MyAnnotation("路由")
    private String route;
 
    @MyAnnotation("用于存储当前目录下面的全部子集")
    private List<PermissionDirectoryResVO> authMenuList;
}
 

树形逻辑

    public List<PermissionDirectoryResVO> searchMenu() {
        
        List<PermissionDirectoryResVO> directoryTree = new ArrayList<>();
        
        List<PermissionDirectory> menuList = permissionDirectoryMapper.getMenuList();
        
        if (CollectionUtil.isNotEmpty(menuList)){
            List<PermissionDirectoryResVO> pdr = menuList.stream().map(PermissionDirectory -> {
                PermissionDirectoryResVO permissionDirectoryResVO = new PermissionDirectoryResVO();
                BeanUtils.copyProperties(PermissionDirectory,permissionDirectoryResVO);
                return permissionDirectoryResVO;
            }).collect(Collectors.toList());
            
            pdr.forEach(e ->{
                List<PermissionDirectoryResVO> pdrList = getChildrenList(e.getId(),pdr);
                e.setAuthMenuList(pdrList != null ? pdrList : null);
            });
            
            List<PermissionDirectoryResVO> parentNodes = pdr.stream().
                    filter(e -> e.getParentId().equals(0)).collect(Collectors.toList());
            directoryTree.addAll(parentNodes);
        }
        return directoryTree;
    }
 
    
     * 获取全部子集
     * @param id
     * @param list
     * @return
     */
    public static List<PermissionDirectoryResVO> getChildrenList(Integer id, List<PermissionDirectoryResVO> list){
        return list.stream().filter(t-> t.getParentId().equals(id)).collect(Collectors.toList());
    }
}
 

代码解释

第一步:创建存储最终结果数据的集合容器
    List<PermissionDirectoryResVO> directoryTree = new ArrayList<>();
 
第二步:获取需要整理成树状结构的所有数据
    List<PermissionDirectory> menuList = permissionDirectoryMapper.getMenuList();
 PS:这里我是通过查询数据获取的数据,练习的话,可以new一些数据出来存入集合中就行了
        
第三步:判断获取的数据是否为空,如果为空的话就没有去整理成树结构的必要了,数据都没有
    if (CollectionUtil.isNotEmpty(menuList)){ .... }
 PS:这里我用的是糊涂类提供的方法进行判断,如果小白在写的过程中发现报错,找不到这个方法或则这个类就换一种写法
        
第四步:将获取的PermissionDirectory数据全部赋值给PermissionDirectoryResVO
     List<PermissionDirectoryResVO> pdr = menuList.stream().map(PermissionDirectory -> {
      PermissionDirectoryResVO permissionDirectoryResVO = new PermissionDirectoryResVO();
      BeanUtils.copyProperties(PermissionDirectory,permissionDirectoryResVO);
      return permissionDirectoryResVO;
     }).collect(Collectors.toList());
  具体解释如下:
        menuList.stream():将menuList集合转换为一个流(Stream)
        map(PermissionDirectory -> {...}):这个简单理解就是循环menuList集合,然后遍历集合中的每一个PermissionDirectory元素
        BeanUtils.copyProperties(PermissionDirectory,permissionDirectoryResVO):将PermissionDirectory对象的属性值复制到permissionDirectoryResVO对象中。这样,authMenuResVO对象就具有了与AuthMenu对象相同的属性值。
        return permissionDirectoryResVO:将转换后的permissionDirectoryResVO对象作为结果返回给调用者。
        collect(Collectors.toList()):将处理后的流中的元素收集到一个新的列表中,并返回该列表
        因此,这段代码的作用是将原始列表menuList中的每个元素转换为AuthMenuResVO类型的对象,并将转换后的对象存储在一个新的列表permissionDirectoryResVO中。
      
第五步:写一个获取子集的方法体
        public static List<PermissionDirectoryResVO> getChildrenList(Integer id, List<PermissionDirectoryResVO> list){
         return list.stream().filter(t-> t.getParentId().equals(id)).collect(Collectors.toList());
     }
       具体解释如下:
           forEach(e -> {...}):是list对象的一个方法,用于遍历该列表(或集合)中的每个元素,并对每个元素执行一段操作。
           e -> {...}是一个Lambda表达式,表示对每个元素执行的操作,相当于e就是PermissionDirectoryResVO元素对象
           因此,这段代码就是通过传递一个主键id和一个PermissionDirectoryResVO集合对象参数,然后遍历循环PermissionDirectoryResVO对象集合,把每一个对象的父目录id和传递过来的参数id进行对比,如果父目录id等于参数id就把这个对象收集到新的集合中,最后作为参数返回。
 
第六步:遍历全部数据,利用递归思想,获取全部的子集
         pdr.forEach(e ->{
           List<PermissionDirectoryResVO> pdrList = getChildrenList(e.getId(),pdr);
            e.setAuthMenuList(pdrList != null ? pdrList : null);
           });
  具体解释如下:
            List<PermissionDirectoryResVO> pdrList = getChildrenList(e.getId(),pdr);这一步通过调用第五步写好的方法已经获取到了全部子集,就是说,如果所有数据一集目录有三个,分别是1、2、3,那么当循环完的时候会有3个pdrList集合,每个集合中分别装有1目录下的数据、2目录下的数据、3目录下的数据。
            当每一次循环的时候,都会对pdr集合中的元素进行一次判断,e.setAuthMenuList(pdrList != null ? pdrList : null);使用三目运算符,如果pdrList集合不为空就表示当前元素有子集,然把pdrList集合赋值给元素的authMenuList属性,如果为空就表示没有子集,赋值空就可以。
            当集合遍历完毕,数据情况看图①实例
            
第七步:获取所有顶点数据
           List<PermissionDirectoryResVO> parentNodes = pdr.stream().
             filter(e -> e.getParentId().equals(0)).collect(Collectors.toList());
           directoryTree.addAll(parentNodes);
     具体解释如下:
               判断pdr集合中父目录id为0的数据,然后赋值给新的parentNodes,最后把这个集合存进directoryTree集合容器中
 

第二种写法:

  • 27
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值