java将有父子关系的list转换为树形结构

简介: java将有父子关系的list转换为树形结构

项目需求:

在项目对接过程中,被调用方给返回了一个对象列表,对象中包含id和parentId,但返回的数据没有层级结构,需要调用方自己组装成树级结构;

需求分析:

由于返回的是否无序的列表,首先需要找到顶级结构,然后更加parentId获取子级,递归循环,指定子级没有后代信息;

需求实现:

想到两种方式:
第一种、首先想到的是循环列表,对一个列表进行多次循环,每次只找一级,即可实现;
第二种、先根据parentId聚合,然后再对聚合map进行递归;

相对来说第二种方式,比较合适;但是需要考虑到parentId不存在的情况;

  • 先找到顶级,过滤条件为parentId不存在:
//没有parentid
        List<TemplateInfo> topList =
            templateInfoList.stream()
                .filter(templateInfo -> !StringUtils.hasText(templateInfo.getFdParentId()))
                .collect(Collectors.toList());
  • 剩下的是有parentid属性的列表:
 //非顶级目录
        List<TemplateInfo > childList =
            templateInfoList.stream()
                .filter(templateInfo -> StringUtils.hasText(templateInfo.getFdParentId()))
                .collect(Collectors.toList());
  • 对非顶级目录进行groupingby聚合
  Map<String,List<TemplateInfo>>  parentIdMap = childList.stream().collect(Collectors.groupingBy(TemplateInfo::getFdParentId));
  • 比较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;
    }

其他实现方法:

以上实现方法,还是有点麻烦,还在找一种更方便快速的方法实现;

相关文章
|
5月前
|
存储 安全 Java
【Java集合类面试二十五】、有哪些线程安全的List?
线程安全的List包括Vector、Collections.SynchronizedList和CopyOnWriteArrayList,其中CopyOnWriteArrayList通过复制底层数组实现写操作,提供了最优的线程安全性能。
|
5月前
|
Java
【Java集合类面试二十三】、List和Set有什么区别?
List和Set的主要区别在于List是一个有序且允许元素重复的集合,而Set是一个无序且元素不重复的集合。
|
3月前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
79 5
|
3月前
|
Java 程序员 编译器
Java|如何正确地在遍历 List 时删除元素
从源码分析如何正确地在遍历 List 时删除元素。为什么有的写法会导致异常,而另一些不会。
80 3
|
3月前
|
Java 程序员
Java|List.subList 踩坑小记
不应该仅凭印象和猜测,就开始使用一个方法,至少花一分钟认真读完它的官方注释文档。
41 1
|
4月前
|
Java 数据处理
技术分享:高效与灵活并存——Java版通用树形结构转换工具的实现与应用
在软件开发中,树形结构的数据表现形式无处不在,从文件系统的目录树到组织架构的部门树,再到各类产品的分类结构。处理这些具有层级关系的数据时,将其转换为树形结构以便展示和操作显得尤为重要。Java作为一门成熟的编程语言,虽然提供了强大的集合框架,但并未直接提供树形结构转换的内置工具。因此,开发一个高效且灵活的通用树形结构转换工具成为许多项目中的必备需求。
128 2
|
5月前
|
Java
用JAVA架建List集合为树形结构的代码方法
这段代码定义了一个表示树形结构的 `Node` 类和一个用于构建树形结构的 `TreeController`。`Node` 类包含基本属性如 `id`、`pid`、`name` 和 `type`,以及子节点列表 `children`。`TreeController` 包含初始化节点列表并将其转换为树形结构的方法。通过过滤和分组操作实现树形结构的构建。详情可见:[代码示例链接1](http://www.zidongmutanji.com/zsjx/43551.html),[代码效果参考链接2](https://www.257342.com/sitemap/post.html)。
55 5
|
4月前
|
Java API 开发者
代码小妙招:用Java轻松获取List交集数据
在Java中获取两个 `List`的交集可以通过 `retainAll`方法和Java 8引入的流操作来实现。使用 `retainAll`方法更为直接,但会修改原始 `List`的内容。而使用流则提供了不修改原始 `List`、更为灵活的处理方式。开发者可以根据具体的需求和场景,选择最适合的方法来实现。了解和掌握这些方法,能够帮助开发者在实际开发中更高效地处理集合相关的问题。
122 1
|
5月前
|
存储 Java API
【Java高手必备】揭秘!如何优雅地对List进行排序?掌握这几种技巧,让你的代码瞬间高大上!
【8月更文挑战第23天】本文深入探讨了Java中对List集合进行排序的各种方法,包括使用Collections.sort()、自定义Comparator以及Java 8的Stream API。通过示例代码展示了不同情况下如何选择合适的方法:从简单的整数排序到自定义类对象的排序,再到利用Comparator指定特殊排序规则,最后介绍了Stream API在排序操作中的简洁应用。理解这些技术的区别与应用场景有助于提高编程效率。
189 4
|
5月前
|
存储 Java 索引