前言
- 场景复现:之前修改了个bug,父子层级树根据 parentCode+level 俩个条件生成树状结构(源代码不是我写的,个人觉得没有必要),结果修改时只修改了当前层级的 parentCode,并没有修改其子层级的 level,导致树状结构不显示其子层级信息。
- 解决方案:在修改当前层级的 parentCode 时,修改其所有子层级的 level,使其与当前层级的 level 对应,简单来说就是将 level +1。
- 原理实现:首先查询到其所有子层级,处理其子层级的 level,并 递归 查询其子层级的子层级,处理每个子层级的 level。
提示:以下是本篇文章正文内容,下面案例可供参考
一、递归是啥
- 递归一句话通俗讲就是一个方法自动重复调用自己的过程。
- 因为是重复调用自己了,所以为了避免内存溢出,我们需要在方法里加一个返回值判断,用于递归循环的跳出。
二、简单示例
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);
}
}
}
总结
把眼泪留给最疼你的人,把微笑留给伤你最深的人。一直往前走,别往后看。顺其自然,内心就会逐渐清朗,时光越老,人心越淡。