背景与转换条件
我们在实际业务中经常会用到树形结构的列表,但是但是对于后端来说数据直接从数据库里面取出的一般都是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() 方法挑选出根节点的那颗树即可。