《《《java代码递归(多级菜单递归遍历成树)
一:正常递归:
亲测可用:思路是知道从父节点一直循环遍历查到子节点
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 }
每天多努力一点,你将会变得更好。

浙公网安备 33010602011771号