Java 中数组转树【超级简单 / 完整代码】

82 阅读1分钟

我们从数据库中查出来的数据是一个List,如何把这个平数组转换成树形结构呢?假定有如下实体:

@Data
public class Category {
    private Long id;

    private String title;

    private Long parentId;

    private List<Category> children;
}

从数据库查出来的只有id,title,parentId ,我们要利用parentId 把父子关系组织起来(顶层 CategoryparentIdnull)。先上代码:

private List<Category> buildTree(List<Category> all) {
      for (Category curr : all) {
          Long pid = curr.getParentId();

          Optional<Category> parentOptional = all.stream().filter(ca -> ca.getId().equals(pid)).findFirst();
          if (parentOptional.isPresent()) { // 相当于 !parentOptional.isEmpty()
              Category p = parentOptional.get();
              if (null == p.getChildren()) {
                  p.setChildren(new ArrayList<>());
              }
              p.getChildren().add(curr);
          }
      }

      return all.stream().filter(ca -> ca.getParentId() == null).toList();
  }
  1. 上述代码主要在遍历里用了 List 的 stream() 相关接口,快速找到当前这一条记录的父节点,然后把当前这一条记录放到其父节点的 children 中。
  2. 因为对象是地址引用,这里一个 Category 是先被当作父节点处理(在其中插入子节点)还是被当作子节点处理(插入到另一个节点的children中)并不影响最终结果。
  3. 同样因为对象是地址引用,即使一个对象被插入到另一个对象的 children 中了,本来的平数组(all),里面一样保留了一份引用,这样这个对象还在遍历中,后续还是会被处理到的。
  4. 所以逻辑就变得非常简单,一言以敝之,每个节点找到自己的父节点即可。
  5. 最后,把所有父节点为null 的都找出来。它们是顶层节点,拔出萝卜带出泥,全部节点就出来了。
  6. 这个算法的优点是对原来平数组中的节点顺序没有要求,而其他有些算法需要保证父节点先出现,有些算法需要保证子节点先出现。