您的当前位置:首页正文

【Java 树形结构】

2024-11-27 来源:个人技术集锦

基本思路

在开发的时候我们会遇到树状的结构,例如 部门、菜单等信息。

代码

我们先进行数据库中的设计

@Data
public class Department implements Serializable {
  private Integer id;
  private String name;
  private String nameEn;
  private Integer parentId;
  @TableField("`order`")
  private Integer order;
  /**
   * 存储格式英文逗号分隔1,8,9
   */
  private String childIds;
  private Integer createBy;
  private String createDate;
  private Integer updateBy;
  private String updateDate;
  /**
   * 0正常-1删除
   */
  private Integer delFlag;

  @TableField(exist = false)
  List<Department> child = new ArrayList<>();

  private String parentRelation;//父部门简称   
  private String parentRelationIds;//父部门id 链路  1,2,3

  @TableField(exist = false)
  List<User> userList = new ArrayList<>();

  public Department(Integer id) {
    this.id = id;
  }
  public Department() {
  }
}

Controller

  @GetMapping("/deptTreeUser")
  public ApiResponse<Department> deptTreeUser(Integer id) {
    return ApiResponse.success(departmentService.deptTreeUser(id));
  }

Service

  public Department deptTree(Integer deptRootId) {
    if (deptRootId == null) {
      return deptTree();
    }
    //order只是保证了同级部门之间的相对顺序
    List<Department> departmentList = listByCache().stream().sorted(Comparator.comparing(v -> v.getOrder())).collect(Collectors.toList());
    Department root = departmentList.stream().filter(v -> v.getId().equals(deptRootId)).findFirst().get();
    root.setChild(departmentList.stream().filter(v -> v.getParentId().equals(root.getId())).collect(Collectors.toList()));
    return getDepartments(departmentList,root.getChild(), root);
  }

这个方法的目的是从数据库中查询出部门信息后,将信息按照order进行排序构建树,然后查询出它的子部门

listByCache方法

  private List<Department> listByCache() {
    List<Department> departmentList=redisTemplate.opsForList().range(DEPARTMENT_KEY,0,-1);
    if (CollectionUtil.isEmpty(departmentList)) {
    // 获取所有部门的信息
      departmentList = list();
      redisTemplate.opsForList().leftPushAll(DEPARTMENT_KEY, departmentList);
    }
    return departmentList;
  }

这个方法的目的就是从数据库中查询部门信息

  private Department getDepartments(List<Department> departmentAllList,List<Department> departmentList, Department root) {
    if (CollectionUtil.isNotEmpty(departmentList)) {
      for (Department department : departmentList) {
        List<Department> tempList2 = departmentAllList.stream().filter(v -> v.getParentId().equals(department.getId())).collect(Collectors.toList());
        department.setChild(tempList2);
        getDepartments(departmentAllList, tempList2, department);
      }
    }
    return root;
  }

这个方法的目的就是构建树,构建子部门的树。这样返回root就可以把部门按照树形的结构进行展示了。

扩展

如果我们想在相应的部门下面进行添加人员呢?
这个时候,我们我们只需要在部门实体里面增加上

  @TableField(exist = false)
  List<User> userList = new ArrayList<>();

这个字段,然后通过遍历,将用户的信息添加进去即可。

获取所有的用户信息

  public Department deptTreeUser(Integer deptRootId) {
    Department department=deptTree(deptRootId);
    List<User> list= userDepartmentService.listUserByLocal();
    addUserForDept(department.getChild(), list);
    department.setUserList(list.stream().filter(v -> v.getMainDepartment().equals(department.getId())).collect(Collectors.toList()));
    return department;
  }
  private void addUserForDept(List<Department> child, List<User> list) {
  for (Department department : child) {
    List<User> tempList=list.stream().filter(v -> v.getMainDepartment().equals(department.getId())).collect(Collectors.toList());
    department.setUserList(tempList);
    addUserForDept(department.getChild(), list);
  }
}
显示全文