IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 飘乙己:List转Tree有4种写法! -> 正文阅读

[Python知识库]飘乙己:List转Tree有4种写法!

作者:>

孔乙己说:回字有四种写法。

飘乙己也说,list转tree也有4种写法,你用的是哪种?

需求场景

有下面一张区域表,典型的树形结构设计。

image-20210625110242489

现前端需要后端返回树形数据结构用于构造展示树。

image-20210628124838191

本篇文章我们就来介绍一下在这种场景下后端构建树形数据结构,也就是通过list转tree的4种写法。

代码实战

  1. 首先我们根据数据库结构创建实体对象
/**
 * 区域平台
 * @author:Jam
 */
@Data
public class Platform {
    private String id;
    private String parentId;
    private String name;
    private String platformCode;
    private List<Platform> children;

    public Platform(String id, String platformCode,String parentId, String name) {
        this.id = id;
        this.parentId = parentId;
        this.name = name;
        this.platformCode = platformCode;
    }

}
  1. 为了便于演示我们就不连接数据库,而是直接使用Junit5的@BeforeEach注解初始化一份结构数据。
public class PlatformTest {

    private final List<Platform> platformList = Lists.newArrayList();
    private ObjectMapper objectMapper = new ObjectMapper();

    @BeforeEach
    private void init(){
        Platform platform0 = new Platform("1","001","0","集团");
        Platform platform1 = new Platform("2","QYPT001","1","销委会");
        Platform platform2 = new Platform("3","QYPT002","2","吉龙大区");
        Platform platform3 = new Platform("4","QYPT003","2","江苏大区");
        Platform platform4 = new Platform("5","QYPT004","4","南京分区");

        Platform platform5 = new Platform("6","QYPT005","1","教育BG");
        Platform platform6 = new Platform("7","QYPT006","6","华南大区");
        Platform platform7 = new Platform("8","QYPT007","6","华东大区");

        platformList.add(platform0);
        platformList.add(platform1);
        platformList.add(platform2);
        platformList.add(platform3);
        platformList.add(platform4);
        platformList.add(platform5);
        platformList.add(platform6);
        platformList.add(platform7);
    }

}

最无节操的写法

这种写法毫无节操可言,全部通过数据库递归查询。

  1. 首先查到根节点,parent_id = 0
  2. 通过根节点id获取到所有一级节点,parent_id = 1
  3. 递归获取所有节点的子节点,然后调用setChildren()方法组装数据结构。

这种写法我就不展示了,辣眼睛。都2021年了我见过不止一次在项目中出现这种写法。

双重循环

这种写法比较简单,也是比较容易想到的。通过双重循环确定父子节点的关系。

@SneakyThrows
@Test
public void test1(){
  System.out.println(platformList.size());
  List<Platform> result = Lists.newArrayList();
  for (Platform platform : platformList) {

    //获取根节点
    if(platform.getParentId().equals("0")){
      result.add(platform);
    }

    for(Platform child : platformList){
      if(child.getParentId().equals(platform.getId())){
        platform.addChild(child);
      }
    }
  }

  System.out.println(objectMapper.writeValueAsString(result));
}

同时需要给Platform添加一个addChild()的方法。

public void addChild(Platform platform){
  if(children == null){
    children = new ArrayList<>();
  }
  children.add(platform);
}

双重遍历

第一次遍历借助hashmap存储父节点与子节点的关系,第二次遍历设置子节点,由于map中已经维护好了对应关系所以只需要从map取即可。

@SneakyThrows
@Test
public void test2(){
  Map<String, List<Platform>> platformMap = new HashMap<>();

  platformList.forEach(platform -> {
    List<Platform> children = platformMap.getOrDefault(platform.getParentId(), new ArrayList<>());
    children.add(platform);
    platformMap.put(platform.getParentId(),children);
  });

  platformList.forEach(platform -> platform.setChildren(platformMap.get(platform.getId())));

  List<Platform> result = platformList.stream().filter(v -> v.getParentId().equals("0")).collect(Collectors.toList());

  System.out.println(objectMapper.writeValueAsString(result));

}

Stream 分组

@SneakyThrows
@Test
public void test4(){
  Map<String, List<Platform>> groupMap = platformList.stream().collect(Collectors.groupingBy(Platform::getParentId));
  platformList.forEach(platform -> platform.setChildren(groupMap.get(platform.getId())));
  List<Platform> collect = platformList.stream()
    .filter(platform -> platform.getParentId().equals("0")).collect(Collectors.toList());
  System.out.println(objectMapper.writeValueAsString(collect));
}

此处主要通过Collectors.groupingBy(Platform::getParentId)方法对platformList按照parentId进行分组,分组后父节点相同的都放一起了。

然后再循环platformList,给其设置children属性。

执行完成后已经形成了多颗树,最后我们再通过filter()方法挑选出根节点的那颗树即可。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-09-13 09:13:47  更:2021-09-13 09:15:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 14:35:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码