Java中实现多级菜单的列表(递归排序)

本文介绍了一种使用递归实现多级菜单展示的方法,通过实体类转换和递归调用,可以灵活地展示任意层级的菜单结构,适用于各种复杂的菜单需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、项目背景

由于最近项目中需要实现展示菜单功能,菜单是需要多级,并且级数不固定。像这种需求,一般就是用递归实现了,可以从第一级一直往下查,一直查询到为空为止。

二、数据库实体类字段

  1. 两个实体类,一个是对应数据库的实体类,VO是返回给前端的实体类
public class RcMenu {
	
	private Integer menuId; //菜单ID
	
	private String menuName;//菜单名称
	
	private Boolean status; //菜单状态
	
	private String level; 	//菜单级别
	
	private Integer parentId; //父类ID
	
	private Integer sortOrder; //排序
	
}
public class RcMenuVO {
	
	private Integer menuId; //菜单ID
	
	private String menuName;//菜单名称
	
	private Boolean status; //菜单状态
	
	private String level; 	//菜单级别
	
	private Integer parentId; //父类ID
	
	private Integer sortOrder; //排序
	
	//存放子菜单目录
	private List<RcMenuVO> children;

}

三、项目中代码实现

	/**
	 * 对象实体类转换
	 * @param rcMenu
	 * @return
	 */
	private RcMenuVO rcMenuTORcMenuVO(RcMenu rcMenu) {
		RcMenuVO rcMenuVO = new RcMenuVO();
		BeanUtils.copyProperties(rcMenu, rcMenuVO);
		return rcMenuVO;
	}


	/**
     * 根据一级递归调用子级
     *	reversed方法 表示数字越大靠前
     * @param menuList
     * @param rootMenuList
     * @return
     */
    private void findSubCategory(List<RcMenu> menuList, List<RcMenuVO> rootMenuList) {
        // 遍历一级
        for (RcMenuVO rcMenuVO : rootMenuList) {
            List<RcMenuVO> rcMenuVOList = new ArrayList<>();
            // 查找子级
            for (RcMenu rcMenu : menuList) {
                // 判断当前目录是否是子父级关系
                if (rcMenuVO.getMenuId().equals(rcMenu.getParentId())) {
                	rcMenuVOList.add(rcMenuTORcMenuVO(rcMenu));
                }
                // 递归调用,不管有几级菜单,都能够适用
                findSubCategory(menuList, rcMenuVOList);
                // 类目显示排序,
                rcMenuVOList.sort(Comparator.comparing(RcMenuVO::getSortOrder));
            }
            // 最后把查到的子级保存到一级目录中
            rcMenuVO.setChildren(rcMenuVOList);
        }
    }

	/**
	 * 	各级菜单列表展示
	 * @param menu
	 * @param pageObject
	 * @return
	 */
	public List<RcMenuVO> queryMenuList(RcMenu menu, PageObject pageObject) {
		List<RcMenu> menuList = null;
		Page<RcMenu> page = PageHelper.startPage(pageObject.getPageNum(), pageObject.getPageSize());
		// 将用户页面提交的参数拷贝到查询条件去
		SpringBeanUtils.copyPropertiesIgnoreNull(pageObject, page);
		//先查出全部菜单
		menuList = menuMapper.queryMenuList(menu);
		
		//获取一级菜单	0代表一级菜单 .reversed()
		List<RcMenuVO> rootMenuList = menuList.stream()
				.filter(e -> e.getParentId().equals(0))
				.map(this::rcMenuTORcMenuVO)
				.sorted(Comparator.comparing(RcMenuVO::getSortOrder))
				.collect(Collectors.toList());
		//查找字节点
		findSubCategory(menuList,rootMenuList);
		
		// 将真实分页信息拷贝到用户页面
		SpringBeanUtils.copyPropertiesIgnoreNull(page, pageObject);
		//返回值		
		return rootMenuList;
	}

	
	/**
	 * 	根据菜单id 查找子菜单
	 * @param menuId
	 * @return
	 */
	public List<RcMenuVO> queryMenuById(RcMenu menu) {
		//先查出菜单
		List<RcMenu> menuList = menuMapper.queryMenuList(menu);
		//获取一级菜单	0代表一级菜单 .reversed()
		List<RcMenuVO> rootMenuList = menuList.stream()
				.filter(e -> e.getParentId().equals(0))
				.map(this::rcMenuTORcMenuVO)
				.sorted(Comparator.comparing(RcMenuVO::getSortOrder))
				.collect(Collectors.toList());
		//查找字节点
		findSubCategory(menuList,rootMenuList);
		//返回值		
		List<RcMenuVO> rootMenu = new ArrayList<RcMenuVO>();
		for (int i = 0; i < rootMenuList.size(); i++) {
			if (rootMenuList.get(i).getMenuId().equals(menu.getMenuId())) {
				RcMenuVO rcMenuVO = rootMenuList.get(i);
				rootMenu.add(rcMenuVO);
			}
		}
		return rootMenu;
	}
	

四、返回的result值 如下:

	{
    "successful": true,
    "data": [
        {
            "menuId": 1,
            "menuName": "菜单",
            "createTime": "2020-05-22",
            "status": "启用",
            "level": "一级菜单",
            "parentId": 0,
            "sortOrder": 0,
            "children": [
                {
                    "menuId": 2,
                    "menuName": "菜单111",
                    "createTime": "2020-05-22",
                    "level": "二级菜单",
                    "parentId": 1,
                    "sortOrder": 1,
                    "status": "停用"
                },
                {
                    "menuId": 3,
                    "menuName": "菜单222",
                    "createTime": "2020-05-22",
                    "level": "二级菜单",
                    "parentId": 1,
                    "sortOrder": 2,
                    "status": "启用"
                }
            ]
        }
    ],
    "page": null,
    "resultHint": "{\"message\":\"数据查询成功\"}",
    "errorPage": "",
    "draw": 0,
    "recordsTotal": 0,
    "recordsFiltered": 0,
    "type": "info"
}
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Monika、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值