《《《java代码递归(多级菜单递归遍历成树)

转载地址:https://blog.csdn.net/qq_36421955/article/details/80846044?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-4

一:正常递归: 

亲测可用:思路是知道从父节点一直循环遍历查到子节点

1.菜单类:

 1 public class Menu {
 2     // 菜单id
 3     private String id;
 4     // 菜单名称
 5     private String name;
 6     // 父菜单id
 7     private String parentId;
 8     // 菜单url
 9     private String url;
10     // 菜单图标
11     private String icon;
12     // 菜单顺序
13     private int order;
14     // 子菜单
15     private List<Menu> childMenus;
16     // ... 省去getter和setter方法以及toString方法
17 
18 }

2.递归主题方法:

 1 /**
 2      * 模块名称
 3      */
 4     public Map<String,Object> testQueryMenuList() {
 5         // 原始的数据
 6        List<Menu> rootMenu = menuDao.queryMenuList(null);
 7        
 8         9           
10        
11         // 最后的结果
12        List<Menu> menuList = new ArrayList<Menu>();
13         // 先找到所有的一级菜单
14        for (int i = 0; i < rootMenu.size(); i++) {
15             // 一级菜单没有parentId
16            if (StringUtils.isBlank(rootMenu.get(i).getParentId())) {
17                menuList.add(rootMenu.get(i));
18            }
19        }
20         // 为一级菜单设置子菜单,getChild是递归调用的
21        for (Menu menu : menuList) {
22            menu.setChildMenus(getChild(menu.getId(), rootMenu));
23        }
24        Map<String, Object> jsonMap = new HashMap<>();
25        jsonMap.put("menu", menuList);
26        //System.out.println(gson.toJson(jsonMap));//使用gson需要在pom.xml引入gson依赖见 2.1步骤
27        //return gson.toJson(jsonMap);//返回类型为String
28         return  jsonMap;
29     }
30 
31     /**
32      * 子方法
33      **/
34     private List<Menu> getChild(String id, List<Menu> rootMenu) {
35         // 子菜单
36        List<Menu> childList = new ArrayList<>();
37        for (Menu menu : rootMenu) {
38             // 遍历所有节点,将父菜单id与传过来的id比较
39            if (StringUtils.isNotBlank(menu.getParentId())) {
40                if (menu.getParentId().equals(id)) {
41                    childList.add(menu);
42                }
43            }
44        }
45         // 把子菜单的子菜单再循环一遍
46        for (Menu menu : childList) {// 没有url子菜单还有子菜单
47     //该节点不含子节点 具体见2.2解释
48             if (StringUtils.isBlank(menu.getUrl())) {
49                 // 递归
50                menu.setChildMenus(getChild(menu.getId(), rootMenu));
51            }
52        } // 递归退出条件
53        if (childList.size() == 0) {
54            return null;
55        }
56        return childList;
57     }
58     

 

 2.1.引入依赖pom.xml

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.2.8</version>
</dependency>

 

2.2  StringUtils.isBlank(menu.getUrl())

这里根据需求可做改动,我这里如果一个菜单有子菜单的话该菜单是没有url的,子菜单才有具体的url跳转,父菜单不用绑定url点击后只展示子菜单并不进行请求接口,
所以没有url的菜单肯定是有子菜单的,有了url的菜单肯定是最终级别分支的菜单,所以对url进行判空决定是否再去查询子菜单

 二:模糊查询

思路:1.根据名称模糊查"节点"数据List<String>
     2.将List<String> “节点”作为条件 or 条件查询返回List<Menu>
     3.循环条件:当节点不为“根节点”时,继续递减
     4.将循环的数据add到最终返回到前端的的List<Menu>

 

将方法返回类型改为List<Menu>,并移除 Map 相关逻辑,直接返回组装好的菜单列表,同时优化了getChild方法返回空列表而非null(避免空指针风险)

 1 import org.apache.commons.lang3.StringUtils;
 2 import java.util.ArrayList;
 3 import java.util.List;
 4 
 5 public class MenuService { // 假设这是菜单服务类,可根据实际类名调整
 6 
 7     // 注入menuDao(实际项目中通过Spring注入等方式)
 8     private MenuDao menuDao;
 9 
10     /**
11      * 模块名称:查询组装树形菜单列表
12      * 变更:返回类型从Map<String,Object>改为List<Menu>
13      */
14     public List<Menu> testQueryMenuList() {
15         // 1. 查询所有原始菜单数据
16         List<Menu> rootMenu = menuDao.queryMenuList(null);
17         
18         // 2. 最终返回的菜单列表(一级菜单)
19         List<Menu> menuList = new ArrayList<>();
20         
21         // 3. 筛选所有一级菜单(parentId为空)
22         for (Menu menu : rootMenu) { // 简化原有的for循环(下标遍历改增强for,更简洁)
23             if (StringUtils.isBlank(menu.getParentId())) {
24                 menuList.add(menu);
25             }
26         }
27         
28         // 4. 为每个一级菜单递归组装子菜单
29         for (Menu menu : menuList) {
30             menu.setChildMenus(getChild(menu.getId(), rootMenu));
31         }
32         
33         // 5. 直接返回组装好的菜单列表(核心变更:移除Map,返回List<Menu>)
34         return menuList;
35     }
36 
37     /**
38      * 递归获取子菜单
39      * 优化:空列表返回new ArrayList<>()而非null,避免空指针
40      */
41     private List<Menu> getChild(String id, List<Menu> rootMenu) {
42         // 子菜单列表
43         List<Menu> childList = new ArrayList<>();
44         
45         // 遍历所有菜单,匹配当前父ID的子菜单
46         for (Menu menu : rootMenu) {
47             if (StringUtils.isNotBlank(menu.getParentId()) && menu.getParentId().equals(id)) {
48                 childList.add(menu);
49             }
50         }
51         
52         // 递归为子菜单设置子菜单(仅当菜单无URL时,说明是父节点,需继续递归)
53         for (Menu menu : childList) {
54             if (StringUtils.isBlank(menu.getUrl())) {
55                 menu.setChildMenus(getChild(menu.getId(), rootMenu));
56             }
57         }
58         
59         // 优化:返回空列表而非null,避免后续调用时出现空指针
60         return childList.isEmpty() ? new ArrayList<>() : childList;
61     }
62 
63     // 内部DAO接口(示例)
64     interface MenuDao {
65         List<Menu> queryMenuList(String parentId);
66     }
67 }

 

posted @ 2020-05-27 14:21  贩卖长江水  阅读(4301)  评论(0)    收藏  举报