Java中递归的实际应用


前言

  • 场景复现:之前修改了个bug,父子层级树根据 parentCode+level 俩个条件生成树状结构(源代码不是我写的,个人觉得没有必要),结果修改时只修改了当前层级的 parentCode,并没有修改其子层级的 level,导致树状结构不显示其子层级信息。
  • 解决方案:在修改当前层级的 parentCode 时,修改其所有子层级的 level,使其与当前层级的 level 对应,简单来说就是将 level +1。
  • 原理实现:首先查询到其所有子层级,处理其子层级的 level,并 递归 查询其子层级的子层级,处理每个子层级的 level。

提示:以下是本篇文章正文内容,下面案例可供参考

一、递归是啥

  1. 递归一句话通俗讲就是一个方法自动重复调用自己的过程。
  2. 因为是重复调用自己了,所以为了避免内存溢出,我们需要在方法里加一个返回值判断,用于递归循环的跳出。

二、简单示例

1.递归修改子层级信息

@Autowired
private GroupService groupService;

public void updateGroup(GroupEntity groupEntity) {
	// 查询分组
    GroupEntity group = groupService.getById(groupEntity.getId());
    // 修改当前分组其下级分组的level
    setSubGroupLevel(group.getCode());
    // ......
}

private void setSubGroupLevel(String groupCode) {
  	// 新的数据
    List<GroupEntity> subGroupListNew = new ArrayList<>();
    // 查询当前分组的所有下级分组
    List<GroupEntity> subGroupList = groupService.list(
            new LambdaQueryWrapper<GroupEntity>().eq(GroupEntity::getParentCode, groupCode));
    // 如果查询不到子层级,则退出递归
    subGroupList.forEach(vo -> {
    	// 原来的父分组层级,即:其下级层级-1
       int parentOldLevel = vo.getLevel() - 1;
        // 当前分组层级 = 当前分组层级 + (其当前父分组层级 — 其原来的父分组层级)
        vo.setLevel(vo.getLevel() + (group.getLevel() - parentOldLevel));
        subGroupListNew.add(vo);
        // 递归调用查询其子层级的子层级
        setSubGroupLevel(vo.getCode());
    });
    if (subGroupListNew.size() > 0) {
        groupService.updateBatchById(subGroupListNew, 200);
    }
}

2.递归新建一个文件名

新建一个文件名,如果重复则加副本俩字,例:建文件名:测试,如果该文件夹下已经有了测试,则自动生成 测试(副本),若还有相同,则再生成 测试(副本)(副本),以此类推。

@Override
public int insert(ToolboxFile toolboxFile) throws ParseException {
	// 获取文件名
    String fileName = getFileName(toolboxFile.getFileName(), toolboxFile.getFolderId());
    // 省略......
}

/**
 * 设置文件名称,当前文件夹下不能有重复的文件名称,若重复则加 副本 俩字
 * fileName -- 文件名称,folderId -- 当前文件夹id
 */
private String getFileName(String fileName, String folderId) {
	// 查询当前文件夹下是否有该文件名
    ToolboxFile file = this.toolboxFileDao.queryByFileNameAndFolderId(fileName, folderId);
    if (null != file) {
    	// 若有加副本
        fileName = fileName + "(副本)";
        // 递归调用,重复加副本
        fileName = getFileName(fileName, folderId);
        return fileName;
    } else {
        return fileName;
    }
}

3.递归创建树层级结构

可以用递归创建树级结构,代码方便使用了Map结构,实际中可以构造一个 tree 实体类,将其中的 map 数据封装进实体类中即可。

public List<Map<String, Object>> getFolderTree(HttpServletRequest request) {
    Map<String, Object> limit = new HashMap<>();
    limit.put("parentFolderId","-1");
    // 查询最顶层的数据
    List<ToolboxFolder> parentFolders = this.toolboxFolderDao.queryAllByLimit(limit);
    // 查询全部数据
    List<ToolboxFolder> allFolders = this.toolboxFolderDao.queryAllByLimit(null);
    List<Map<String , Object>> result = new ArrayList<>();
    // 循环最外层树
    for (ToolboxFolder toolboxFolder : parentFolders) {
        Map<String , Object> map = new HashMap<>(16);
        map.put("unitGuid",toolboxFolder.getUnitGuid());
        map.put("folderName",toolboxFolder.getFolderName());
        map.put("parentFolderId",toolboxFolder.getParentFolderId());
        // 递归创建树结构
        buildFolderTree(map, allFolders);
        result.add(map);
    }
    return result;
}

private void buildFolderTree(Map<String , Object> parentFolder, List<ToolboxFolder> allFolders){
    for (ToolboxFolder toolboxFolder : allFolders) {
        if(parentFolder.get("unitGuid").toString().equals(toolboxFolder.getParentFolderId())){
            Map<String , Object> tmpChildren = new HashMap<>();
            tmpChildren.put("unitGuid",toolboxFolder.getUnitGuid());
            tmpChildren.put("folderName",toolboxFolder.getFolderName());
            tmpChildren.put("parentFolderId",toolboxFolder.getParentFolderId());
            List<Map<String , Object>> children = null;
            if(null == parentFolder.get("children")){
                children = new ArrayList<>();
            }else {
                children = (List<Map<String , Object>>)parentFolder.get("children");
            }
            children.add(tmpChildren);
            parentFolder.put("children",children);
            buildFolderTree(tmpChildren,allFolders);
        }
    }
}

总结

把眼泪留给最疼你的人,把微笑留给伤你最深的人。一直往前走,别往后看。顺其自然,内心就会逐渐清朗,时光越老,人心越淡。

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
/** * 根据等级查询类目树 * * @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; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值