算法篇-递归算法-构建树结构(二)

愿历尽千帆,归来仍是少年

本篇用于树结构的优化方案

实体类

复制代码
public class CommonTree {
  /**
   * 部门树节点ID
   */
  @ApiModelProperty(value = "树节点ID")
  private Integer id;

  /**
   *  title
   */
  @ApiModelProperty(value = "title")
  private String title;

  /**
   *  title
   */
  @ApiModelProperty(value = "titleEN")
  private String titleEN;

  /**
   *  父部门ID
   */
  @ApiModelProperty(value = "父部门ID")
  private Integer parentId;


  /**
   *  count
   */
  @ApiModelProperty(value = "数量")
  private int count;

  /**
   *  状态
   */
  @ApiModelProperty(value = "状态 (1:启用,2:停用)")
  private Integer status;

  /**
   * 员工ids
   */
  @ApiModelProperty(value = "员工ids")
  private String staffIds;

  /**
   * 主要负责人
   */
  @ApiModelProperty(value = "主要负责人")
  private Integer ownerStaffId;

  /**
   * 下一级子节点对象集合
   */
  @ApiModelProperty(value = "下一级子节点对象集合")
  private List<CommonTree> children;

}
复制代码

1.使用递归构建树结构

复制代码
/**
   * 构建树结构
   * @param list
   * @return
   */
  public static List<CommonTree> buildTree(List<CommonTree> list) {
    List<CommonTree> childrenTreeList = new ArrayList<>();
    List<CommonTree> rootPositionList = new ArrayList<>();
    list.forEach(o -> {
      if (Objects.isNull(o.getParentId()) || 0 == o.getParentId()) {
        rootPositionList.add(o);
      } else {
        childrenTreeList.add(o);
      }
    });

    List<CommonTree> resultList = new ArrayList<>();
    rootPositionList.forEach(o -> {
      o = buildChildrenTree(childrenTreeList, o);
      resultList.add(o);
    });

    return resultList;
  }

  private static CommonTree buildChildrenTree(List<CommonTree> childrenTreeList, CommonTree commonTree) {
    List<CommonTree> childrenList = new ArrayList<>();
    AtomicInteger count = new AtomicInteger();
    childrenTreeList.forEach(o -> {
      if (o.getParentId() == commonTree.getId().intValue()) {
        childrenList.add(buildChildrenTree(childrenTreeList, o));
      }
    });
    commonTree.setChildren(childrenList);
    return commonTree;
  }
复制代码

2.初步优化-使用双重for循环构建树结构

复制代码
  public static List<CommonTree> buildTree(List<CommonTree> list) {
    //List<CommonTree> childrenTreeList = new ArrayList<>();
    List<CommonTree> rootPositionList = new ArrayList<>();
    list.forEach(o -> {
      if (Objects.isNull(o.getParentId()) || 0 == o.getParentId()) {
        rootPositionList.add(o);
      } else {
        childrenTreeList.add(o);
      }
    });
  
    buildChildrenTree(list);

    return rootPositionList;
  }

  private static void buildChildrenTree(List<CommonTree> childrenTreeList) {

    for (int i = 0; i < childrenTreeList.length(); i++){

      CommonTree tree = childrenTreeList.get(i);

      List<CommonTree> childrenList = new ArrayList<>();
      tree.setChildren(childrenList);

      for(int j = 0; j < childrenTreeList.length(); j++){
        CommonTree childTree = childrenTreeList.get(j);
        if (childTree.getParentId() == tree.getId().intValue()) {
          childrenList.add(childTree);
        }
      }
    }
    
  }
复制代码

3.再次优化-使用1.8新特性构建树结构

复制代码
/**
   * 构建树结构
   * @param commonTrees
   * @return
   */
  public static List<CommonTree> buildTree(List<CommonTree> commonTrees) {
    Map<Integer, List<CommonTree>> sub = commonTrees.stream().filter(node -> node.getParentId() != null && node.getParentId() != 0).collect(Collectors.groupingBy(CommonTree::getParentId));
    commonTrees.forEach(node -> node.setChildren(sub.get(node.getId()) == null ? Lists.newArrayList() : sub.get(node.getId())));
    return commonTrees.stream().filter(node -> Objects.isNull(node.getParentId()) || node.getParentId() == 0).collect(Collectors.toList());
  }
复制代码

4.进行逐层树结构数据汇总-此时需要使用递归

复制代码
// 逐层拼接staffIds
list.forEach(CommonTree::getStraffIds);

public static String getStraffIds(CommonTree parentCommonTree) {
    parentCommonTree.getChildren().forEach(o -> {
      if (null != o.getChildren() && o.getChildren().size() > 0) {
        parentCommonTree.setStaffIds(parentCommonTree.getStaffIds() + "," + getStraffIds(o));
      } else {
        parentCommonTree.setStaffIds(parentCommonTree.getStaffIds() + "," + o.getStaffIds());
      }
    });

    // 去重求和
    sumCount(parentCommonTree);
    return parentCommonTree.getStaffIds();
  }

  private static void sumCount(CommonTree parentCommonTree) {
    // 员工数量汇总
    String staffIds = parentCommonTree.getStaffIds();
    if (!StringUtils.isEmpty(staffIds)) {
      List<String> staffIdsLists = Lists.newArrayList(staffIds.split(",")).stream().distinct().collect(Collectors.toList());
      // 去除两种为空情况
      staffIdsLists.removeAll(Collections.singleton("null"));
      staffIdsLists.removeAll(Collections.singleton(""));
      parentCommonTree.setCount(staffIdsLists.size());
      parentCommonTree.setStaffIds(String.join(",", staffIdsLists));
    } else {
      parentCommonTree.setCount(0);
    }
  }
复制代码

 

posted @   归来仍是少年-youg  阅读(226)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示