List转换成树状结构(使用stream流的方式)

背景与转换条件

我们在实际业务中经常会用到树形结构的列表,但是但是对于后端来说数据直接从数据库里面取出的一般都是List集合这样的平面结构,所以我们需要把List集合转成树形结构再返回给前端,前端拿到数据再进行渲染。

一组平面数据(我们也把每个数据对象看做一个树中的一个节点)要能够转化成树形结构需要具备一些特点:

  • 每个节点有自己的唯一id
  • 每个节点都有父节点——一般为parentId
  • 每个节点能够嵌套包含子节点对象

实现树形结构的方法很多,比如对集合进行两次循环(时间复杂度为O(n2))
但是我经常使用的是利用stream流的方式进行转换

利用stream流将List转化成树形结构

以组织机构Organization类为例进行说明

public class Organization{
//机构id
private Long id;
//机构名称
private String OrganizationName;
//机构的父节点id
private Long ParentId;
//机构子节点集合
private List<Organization> children;
}

下面是转化的过程

public List<Organization> selectOrganizationTree() {
    List<Organization> organizations= organizationMapper.selectList(null);
    //操作所有组织机构数据
    Map<Long, List<Organization>> groupMap = organizations.stream().collect(Collectors.groupingBy(Organization::getParentId));
    organizations.forEach(organization-> {
        organization.setChildren(groupMap.get(organization.getId()));
    });
    List<Organization> collect = organizations.stream().filter(organization-> organization.getParentId().equals(0L)).collect(Collectors.toList());
    return collect;
}
此方法主要通过Collectors.groupingBy(Organization::getParentId)方法对organizations按照parentId进行分组,分组后父节点相同的都放一起了。
然后再循环organizations,给其设置children属性。
执行完成后会形成多颗树,最后我们再通过 filter() 方法挑选出根节点的那颗树即可。
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
假设List<TestAlertFileSystem>中的对象包含以下属性:id、name、parentId、size。 按照parentId进行属性聚合并将结果化成三级树形层级结构的示例代码如下: ```java // 定义一个辅助类,用于保存聚合结果 class AggregationResult { private String parentId; private List<TestAlertFileSystem> children; // 省略getter和setter方法 } // 对List<TestAlertFileSystem>按parentId进行聚合 Map<String, List<TestAlertFileSystem>> groupByParentId = list.stream() .collect(Collectors.groupingBy(TestAlertFileSystem::getParentId)); // 将聚合结果转换成三级树形结构 List<AggregationResult> result = groupByParentId.keySet().stream() .map(parentId -> { AggregationResult r = new AggregationResult(); r.setParentId(parentId); List<TestAlertFileSystem> children = groupByParentId.get(parentId); if (children != null && !children.isEmpty()) { Map<String, List<TestAlertFileSystem>> groupByParentId2 = children.stream() .collect(Collectors.groupingBy(TestAlertFileSystem::getId)); List<TestAlertFileSystem> secondLevel = groupByParentId2.keySet().stream() .map(id -> { TestAlertFileSystem t = groupByParentId2.get(id).get(0); List<TestAlertFileSystem> children2 = groupByParentId2.get(id); if (children2 != null && !children2.isEmpty()) { Map<String, List<TestAlertFileSystem>> groupByParentId3 = children2.stream() .collect(Collectors.groupingBy(TestAlertFileSystem::getId)); List<TestAlertFileSystem> thirdLevel = groupByParentId3.keySet().stream() .map(id2 -> groupByParentId3.get(id2).get(0)) .collect(Collectors.toList()); t.setChildren(thirdLevel); } return t; }) .collect(Collectors.toList()); r.setChildren(secondLevel); } return r; }) .collect(Collectors.toList()); ``` 以上代码中,先使用Java 8的式操作对List<TestAlertFileSystem>按parentId进行属性聚合,得到一个Map<String, List<TestAlertFileSystem>>类型的聚合结果,其中Map的key是parentId,value是所有parentId为该值的TestAlertFileSystem对象列表。 接着,将聚合结果转换成三级树形结构。首先使用Map的keySet()方法获取所有不同的parentId值,对于每个parentId值,创建一个AggregationResult对象,并将其parentId设置为该值。然后获取所有parentId为该值的TestAlertFileSystem对象列表,并按id进行属性聚合,得到一个Map<String, List<TestAlertFileSystem>>类型的子聚合结果,其中Map的key是id,value是所有id为该值的TestAlertFileSystem对象列表。 接着,对于每个id值,创建一个TestAlertFileSystem对象,并将其设置为该id值的第二级节点。然后获取所有id为该值的TestAlertFileSystem对象列表,并按id进行属性聚合,得到一个Map<String, List<TestAlertFileSystem>>类型的子聚合结果,其中Map的key是id,value是所有id为该值的TestAlertFileSystem对象列表。然后再对于每个id值,创建一个TestAlertFileSystem对象,并将其设置为该id值的第三级节点,最后将所有第三级节点组成一个列表,设置到该id值的第二级节点的children属性中。 最后将所有AggregationResult对象组成一个列表,就得到了按parentId进行聚合并化成三级树形结构的结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值