需求场景

有下面一张区域表,典型的树形结构设计。
clipboard.png
现前端需要后端返回树形数据结构用于构造展示树。
clipboard.png

代码实战

实验数据构造:
首先我们根据数据库结构创建实体对象

  1. /**
  2. * 区域平台
  3. * @author:Jam
  4. */
  5. @Data
  6. public class Platform {
  7. private String id;
  8. private String parentId;
  9. private String name;
  10. private String platformCode;
  11. private List<Platform> children;
  12. public Platform(String id, String platformCode,String parentId, String name) {
  13. this.id = id;
  14. this.parentId = parentId;
  15. this.name = name;
  16. this.platformCode = platformCode;
  17. }
  18. }

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

  1. public class PlatformTest {
  2. private final List<Platform> platformList = Lists.newArrayList();
  3. private ObjectMapper objectMapper = new ObjectMapper();
  4. @BeforeEach
  5. private void init(){
  6. Platform platform0 = new Platform("1","001","0","集团");
  7. Platform platform1 = new Platform("2","QYPT001","1","销委会");
  8. Platform platform2 = new Platform("3","QYPT002","2","吉龙大区");
  9. Platform platform3 = new Platform("4","QYPT003","2","江苏大区");
  10. Platform platform4 = new Platform("5","QYPT004","4","南京分区");
  11. Platform platform5 = new Platform("6","QYPT005","1","教育BG");
  12. Platform platform6 = new Platform("7","QYPT006","6","华南大区");
  13. Platform platform7 = new Platform("8","QYPT007","6","华东大区");
  14. platformList.add(platform0);
  15. platformList.add(platform1);
  16. platformList.add(platform2);
  17. platformList.add(platform3);
  18. platformList.add(platform4);
  19. platformList.add(platform5);
  20. platformList.add(platform6);
  21. platformList.add(platform7);
  22. }
  23. }

一般方法:

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

    双重循环:

    通过双重循环确定父子节点的关系。 ```java @SneakyThrows @Test public void test1(){ System.out.println(platformList.size()); List 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())){

    1. platform.addChild(child);

    } } }

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

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

  1. <a name="ckThb"></a>
  2. ### 双重遍历:
  3. 第一次遍历借助hashmap存储父节点与子节点的关系,第二次遍历设置子节点,由于map中已经维护好了对应关系所以只需要从map取即可。
  4. ```java
  5. @SneakyThrows
  6. @Test
  7. public void test2(){
  8. Map<String, List<Platform>> platformMap = new HashMap<>();
  9. platformList.forEach(platform -> {
  10. List<Platform> children = platformMap.getOrDefault(platform.getParentId(), new ArrayList<>());
  11. children.add(platform);
  12. platformMap.put(platform.getParentId(),children);
  13. });
  14. platformList.forEach(platform -> platform.setChildren(platformMap.get(platform.getId())));
  15. List<Platform> result = platformList.stream().filter(v -> v.getParentId().equals("0")).collect(Collectors.toList());
  16. System.out.println(objectMapper.writeValueAsString(result));
  17. }

Stream 分组:

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

此处主要通过Collectors.groupingBy(Platform::getParentId)方法对platformList按照parentId进行分组,分组后父节点相同的都放一起了。
然后再循环platformList,给其设置children属性。
执行完成后已经形成了多颗树,最后我们再通过filter()方法挑选出根节点的那颗树即可。