java将有父子关系的list转换为树形结构
2023-02-25 18:17:12 时间
项目需求:
在项目对接过程中,被调用方给返回了一个对象列表,对象中包含id和parentId,但返回的数据没有层级结构,需要调用方自己组装成树级结构;
需求分析:
由于返回的是否无序的列表,首先需要找到顶级结构,然后更加parentId获取子级,递归循环,指定子级没有后代信息;
需求实现:
想到两种方式:
第一种、首先想到的是循环列表,对一个列表进行多次循环,每次只找一级,即可实现;
第二种、先根据parentId聚合,然后再对聚合map进行递归;
相对来说第二种方式,比较合适;但是需要考虑到parentId不存在的情况;
- 先找到顶级,过滤条件为parentId不存在://没有parentid List<TemplateInfo> topList = templateInfoList.stream() .filter(templateInfo -> !StringUtils.hasText(templateInfo.getFdParentId())) .collect(Collectors.toList()); //非顶级目录 List<TemplateInfo > childList = templateInfoList.stream() .filter(templateInfo -> StringUtils.hasText(templateInfo.getFdParentId())) .collect(Collectors.toList()); Map<String,List<TemplateInfo>> parentIdMap = childList.stream().collect(Collectors.groupingBy(TemplateInfo::getFdParentId));
- 剩下的是有parentid属性的列表:
- 对非顶级目录进行groupingby聚合
- 比较parentId和id集合,获取到顶级下的第二级 对两个id列表进行set,然后通过set的removeAll方法过滤到id Set<String> idSet = childList.stream().map(templateInfo -> templateInfo.getFdId()).collect(Collectors.toSet()); Set<String> parentIdSet = parentIdMap.keySet(); HashSet<String> set = new HashSet<>(); set.addAll(parentIdSet); set.removeAll(idSet); //剩下的就是顶级目录
- 对map进行递归操作,添加到后代节点;
List<CategoryInfo> categoryInfos = new ArrayList<>();
for (String parentId : set) {
categoryInfos.addAll(genTree(parentId,parentIdMap,1));
}
递归函数
public List<CategoryInfo> genTree(String parentId,Map<String,List<TemplateInfo>> parentIdMap,int level){
List<CategoryInfo> categoryInfoList = new ArrayList<>();
List<TemplateInfo> templateInfos = parentIdMap.get(parentId);
if(templateInfos==null){
//do noting
}else{
level = level + 1;
System.out.println(level+"==" + parentId);
for (TemplateInfo templateInfo:templateInfos) {
List<InnerCategoryInfo> chlidList = genTree(templateInfo.getFdId(),parentIdMap,level);
InnerCategoryInfo categoryInfo = new InnerCategoryInfo(templateInfo.getFdId(),
templateInfo.getFdName(),templateInfo.getFdParentId(),level,chlidList);
categoryInfoList.add(categoryInfo);
}
}
return categoryInfoList;
}
- 之前由于对list列表以parentId为key进行聚合,如果parentId为null或空字符串,聚合时会报错,所以排除了parentId不存在的对象;这里需要添加到顶级
public List<CategoryInfo> genTree(List<TemplateInfo> templateInfoList){
List<CategoryInfo> top = new ArrayList<>();
if(topList!=null && topList.size() > 0){
Map<String,List<CategoryInfo>> categoryInfoTop =
categoryInfos.stream().collect(Collectors.groupingBy(CategoryInfo::getParentId));
for (TemplateInfo t : topList) {
InnerCategoryInfo info = new CategoryInfo(t.getFdId(),t.getFdName(),
t.getFdParentId(),0,categoryInfoTop.get(t.getFdId()));
top.add(info);
}
categoryInfos = top;
}
return categoryInfos;
}
其他实现方法:
以上实现方法,还是有点麻烦,还在找一种更方便快速的方法实现;
相关文章
- 十大 Java 语言特性
- JVM 三色标记算法,原来是这么回事!
- 聊聊 Spring 事务控制策略以及 @Transactional 失效问题避坑
- 写给 Java 程序员的前端 Promise 教程
- 写给 Java 程序员的前端 Promise 教程,你学会了吗?
- Java 中为什么不全部使用 Static 方法?
- Java 池化技术你了解多少?
- Java 服务 Docker 容器化优秀实践
- Spring Boot + EasyExcel导入导出,简直太好用了!
- 我们一起聊聊 Java 内存泄漏
- CentOS 下安装 Docker 极简教程
- JDK 19 功能集冻结:Java 19 只有七个新特性
- 关于 CMS 垃圾回收器,你真的懂了吗?
- 为什么会有这么多编程语言?
- 改善Java代码的八个建议
- 接口流量突增,如何做好性能优化?
- Java 以编程方式创建JAR文件
- POJO、Java Bean是如何定义的
- Spring 的 Bean 明明设置了 Scope 为 Prototype,为什么还是只能获取到单例对象?
- 面试官问我JVM的GC分代收集算法为什么这么设计