Java8新特性Stream——优雅的递归遍历树形结构, 递归删除节点

本文介绍了如何在Java中处理树形结构数据,包括构建层级菜单、递归遍历以及根据ID删除节点及其所有子节点。示例中使用了Lombok注解简化代码,并展示了结合MybatisPlus框架进行递归删除的实现。

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

日常开发中会碰需要树形结构数据,层级菜单显示,或者是根据指定id删除该id和其包含的所有子节点,下面简单分享一下,如有错误,还请大佬指点

  1. 菜单实体类
/**
 * <p>菜单实体类</p>
 * @author : Zyy
 * @date : 2020-12-26 17:41
 **/
 
@Data //lombok注解,自动生成set和get方法
public class Menu {

    //id
    private String id;

    //菜单名
    private String name;

    //父节点id
    private String pid;

    //子节点信息
    private List<Menu> children;

	//无参构造
    public Menu() {}
    
    //带参构造
    public Menu(String id, String name, String pid) {
        this.id = id;
        this.name = name;
        this.pid= pid;
    }

}
  1. 递归遍历树形结构
    public void getTreeMenu() {
        //模拟数据库查出所有数据
        List<Menu> menus = Arrays.asList(
                new Menu(1, "根节点", 0),
                new Menu(2, "子节点1", 1),
                new Menu(3, "子子节点1.1", 2),
                new Menu(6, "子子子节点1.1.1", 3),
                new Menu(4, "子节点2", 1),
                new Menu(5, "子子节点2.1", 4)
        );

        //筛选出根节点
        List<Menu> list = menus.stream().filter(menu -> "0".equals(menu.getPid())).peek(
            //设置子节点信息
            menu -> menu.setChildren(getChildrens(menu, menus))
        ).collect(Collectors.toList());
    }
	
	private List<Menu> getChildrens(Menu root, List<Menu> menus) {
     	List<Menu> list = menus.stream().filter(menu ->
     		//筛选出下一节点元素
   			Objects.equals(menu.getPid(), root.getId())).map(menu -> {
   				//递归set子节点
				menu.setChildren(this.getChildrens(menu, menus));
                return menu;
          	}).collect(Collectors.toList());	
        return list;
    }

	
  1. 递归删除节点及其子节点(结合MybatisPlus框架)
	public void deleteMenus(String id) {
		//存储所有要删除的id
		List<String> idList = new ArrayList<>();
		//获得所有需要删除的id
		this.selectChildListById(id, idList);
		//添加删除的节点id
		idList.add(id);
		//MybatisPlus批量删除方法
		baseMapper.deleteBatchIds(idList);
	}
	
	private String selectChildListById(String id, List<String> idList) {
		//查询数据库pid等于id的数据
		List<Menu> childList = baseMapper.selectList(new QueryWrapper<Menu>().eq("pid", id).select("id"));
		//递归查询下一级id,同时将上一次查询结果添加到list集合
        childList.forEach(menu-> {
            idList.add(menu.getId());
            this.selectChildListById(menu.getId(), idList);
        });
	}
	
/** * 根据等级查询类目树 * * @param level * @return */ @Override public List queryCategoryTree(Integer level) { //查询当前级别下类目 List list = categoryDAO.list(level); //组装好的类目树,返回前端 List categoryTree = new ArrayList(); //所有类目 List allDTOList = new ArrayList(); if (CollectionUtils.isEmpty(list)) { return categoryTree; } for (CategoryDO categoryDO : list) { allDTOList.add(new CategoryTreeDTO().convertDOToDTO(categoryDO)); } //当前等级类目 categoryTree = allDTOList.stream().filter(dto -> level.equals(dto.getLevel())).collect(Collectors.toList()); for (CategoryTreeDTO categoryTreeDTO : categoryTree) { //组装类目为树结构 assembleTree(categoryTreeDTO, allDTOList,Constants.CATEGORY_MAX_LEVEL - level); } return categoryTree; } /** * 组装树 * * @param categoryTreeDTO * @param allList * @param remainRecursionCount 剩余递归次数 * @return */ public CategoryTreeDTO assembleTree(CategoryTreeDTO categoryTreeDTO, List allList, int remainRecursionCount) { remainRecursionCount--; //最大递归次数不超过Constants.CATEGORY_MAX_LEVEL-level次,防止坏数据死循环 if(remainRecursionCount < 0){ return categoryTreeDTO; } String categoryCode = categoryTreeDTO.getCategoryCode(); Integer level = categoryTreeDTO.getLevel(); //到达最后等级树返回 if (Constants.CATEGORY_MAX_LEVEL == level) { return categoryTreeDTO; } //子类目 List child = allList.stream().filter(a -> categoryCode.equals(a.getParentCode())).collect(Collectors.toList()); if (null == child) { return categoryTreeDTO; } categoryTreeDTO.setChildren(child); //组装子类目 for (CategoryTreeDTO dto : child) { assembleTree(dto, allList,remainRecursionCount); } return categoryTreeDTO; }
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值