算法已经改进,请看最新:https://blog.csdn.net/u011060906/article/details/98942421
这个是单一根节点的,如果需要多根节点的参考:https://blog.csdn.net/u011060906/article/details/88549862
最近需要做一个N级菜单的查询,所以想到了递归,这里就简单写一下思路
首先退出条件就是入参菜单list的size为0
其次就是没查到顶级菜单,直接退出
剩下的就是重点,循环遍历入参菜单,比较每个菜单的父菜单的id是否存在返回菜单中,如果存在,就把它从入参菜单移动到返回菜单中,这时递归调用,将新的子菜单当作返回菜单这样就可以保证每个子菜单的子菜单都会被判断到。
这里就不考虑效率问题了,这中办法时间复杂度和空间复杂的都太高了,毕竟菜单不会超级多。
直接上代码:
List<AppMenu> back = new ArrayList<AppMenu>();
//数据库中查询出来的没有层级关系的菜单当作入参,appMenus
List<AppMenu> appMenus = appMenuMapper.findAppMenusByPd(pd);
//调用菜单整理方法进行整理
getAppMenu(appMenus, back);
//排序
Collections.sort(back);
核心代码:
/**
* 整理菜单
*
* 将没有层级关系的菜单变成有层级关系的菜单
*
* @param appMenus
* 没有层级关系的菜单
* @param back
* 返回的菜单
*/
public void getAppMenu(List<AppMenu> appMenus, List<AppMenu> back) {
if (appMenus.size() <= 0) {
// 菜单加入完毕,退出
return;
} else if (back.size() <= 0) {
// 菜单刚刚开始加入,先找出顶级菜单
for (int i = 0; i < appMenus.size(); i++) {
if (appMenus.get(i).getParentId() == 0) {
back.add(appMenus.get(i));
appMenus.remove(appMenus.get(i--));
continue;
}
}
// 没找到顶级菜单,直接退出
if (back.size() <= 0) {
return;
}
// 存在顶级菜单,递归调用,找出下级菜单
getAppMenu(appMenus, back);
} else {
// 加入菜单
for (int i = 0; i < appMenus.size(); i++) {
for (int j = 0; j < back.size(); j++) {
if (appMenus.get(i).getParentId() == back.get(j).getId()) {
// 判断当前菜单是否存在子菜单
if (back.get(j).getSubAppMenu() == null) {
List<AppMenu> appSubMenus = new ArrayList<AppMenu>();
appSubMenus.add(appMenus.get(i));
back.get(j).setSubAppMenu(appSubMenus);
} else {
back.get(j).getSubAppMenu().add(appMenus.get(i));
}
appMenus.remove(appMenus.get(i--));
// 下级菜单
getAppMenu(appMenus, back.get(j).getSubAppMenu());
break;
}
}
}
}
return;
}