From 2101b352f4304076ef082b34dc35da240950aa08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=80=A1?= Date: Thu, 19 Jun 2025 18:22:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BB=84=E7=BB=87=E6=9C=BA?= =?UTF-8?q?=E6=9E=84=E6=A0=91=E6=9E=84=E5=BB=BA=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BA=E6=A0=B9=E6=8D=AE=E6=A0=B9=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E5=B1=95=E7=A4=BA=E5=A4=9A=E6=9D=A1=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E5=A4=9A=E7=BA=A7=E6=9C=BA=E6=9E=84?= =?UTF-8?q?=E5=B9=B6=E6=8F=90=E5=8D=87=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 重构`getTreeByNode`方法: - 新增父节点到子节点的映射表(parentToChildrenMap),通过预处理将子节点查找时间从O(n)优化为O(1) - 使用StringBuilder累加部门ID,避免字符串拼接的性能损耗 - 提前将SysOrg转换为SysOrgVO并应用树形结构字段(id/title/key/value),减少重复转换操作 2. 新增`buildMultiLevelTree`方法: - 独立递归构建多级树的核心逻辑,提升代码可读性 - 通过映射表快速获取子节点列表,支持任意层级的组织机构树构建 - 对每层级子节点按sort字段排序,保持原有展示顺序 3. 移除原低效递归方法`getChildrenNode`,消除全量数据遍历的性能瓶颈 影响范围:组织机构树形查询接口(对应Controller的`/queryAll`端点),显著提升大数据量(20000+条)时的响应速度。 --- .../org/service/impl/SysOrgServiceImpl.java | 126 ++++++++++-------- 1 file changed, 68 insertions(+), 58 deletions(-) diff --git a/src/main/java/com/coscoshipping/ebtp/project/org/service/impl/SysOrgServiceImpl.java b/src/main/java/com/coscoshipping/ebtp/project/org/service/impl/SysOrgServiceImpl.java index 76ee3b0..33dd651 100644 --- a/src/main/java/com/coscoshipping/ebtp/project/org/service/impl/SysOrgServiceImpl.java +++ b/src/main/java/com/coscoshipping/ebtp/project/org/service/impl/SysOrgServiceImpl.java @@ -22,9 +22,7 @@ import com.coscoshipping.ebtp.project.org.service.SysOrgService; import org.springframework.util.CollectionUtils; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -50,8 +48,7 @@ public class SysOrgServiceImpl extends BaseServiceImpl imp @Override public List getTreeByNode(SysOrg org) { - SysOrgVO sysOrgVO = new SysOrgVO(); - List sysOrgList = new ArrayList<>(); + List sysOrgList; if (!StringUtils.isEmpty(org.getOrgName()) || !StringUtils.isEmpty(org.getOrgNum())){ SysOrgVO vo = BeanUtil.toBean(org, SysOrgVO.class); IPage page = this.getPage(vo); @@ -59,33 +56,77 @@ public class SysOrgServiceImpl extends BaseServiceImpl imp return sysOrgList.stream().map(entity -> BeanUtil.toBean(entity, SysOrgVO.class)).collect(Collectors.toList()); } else { sysOrgList = this.list(); - - //存储所有的部门ID - String allDepartmentId = ""; - - if (!CollectionUtils.isEmpty(sysOrgList)) { - //获取要查询的节点ID 如果为空则查询所有节点进行树形展示 - String rootNode = StringUtils.isNotBlank(org.getOrgId()) ? org.getOrgId() : CommonUtil.ROOT_NODE; - - allDepartmentId += rootNode; - - List sysOrgVOList = JsonUtils.jsonToList(sysOrgList, SysOrgVO.class); - //获取要查询的节点 - sysOrgVO = sysOrgVOList.stream() - .filter(n -> StringUtils.equals(n.getUpOrgId(), rootNode)) - .map(this::setInfoForTree) - .collect(Collectors.toList()) - .get(0); - //递归查询节点信息 - getChildrenNode(sysOrgVOList, sysOrgVO, allDepartmentId); - } - sysOrgVO.setAllDepartmentId(allDepartmentId); List voList = new ArrayList<>(); - voList.add(sysOrgVO); + + if (CollectionUtils.isEmpty(sysOrgList)) { + return voList; + } + + // 预处理所有节点为SysOrgVO,并构建子节点映射表 + List allOrgVOs = sysOrgList.stream() + .map(entity -> BeanUtil.toBean(entity, SysOrgVO.class)) + .map(this::setInfoForTree) // 提前应用树形结构转换 + .collect(Collectors.toList()); + + // 构建父节点到子节点的映射(key: upOrgId,value: 子节点列表) + Map> parentToChildrenMap = new HashMap<>(); + String rootOrgCode = "10000000"; + for (SysOrgVO orgVO : allOrgVOs) { + String parentId = StringUtils.isBlank(orgVO.getUpOrgId()) ? rootOrgCode : orgVO.getUpOrgId(); + parentToChildrenMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(orgVO); + } + + // 获取根节点ID + String rootNode = StringUtils.isNotBlank(org.getOrgId()) ? org.getOrgId() : rootOrgCode; + + // 使用StringBuilder记录所有部门ID + StringBuilder allDepartmentIdBuilder = new StringBuilder(rootNode); + + // 构建多级树结构(从根节点开始递归) + List rootChildren = parentToChildrenMap.getOrDefault(rootNode, new ArrayList<>()); + for (SysOrgVO rootChild : rootChildren) { + buildMultiLevelTree(rootChild, parentToChildrenMap, allDepartmentIdBuilder); + voList.add(rootChild); + } + + // 设置全量部门ID + voList.forEach(vo -> vo.setAllDepartmentId(allDepartmentIdBuilder.toString())); + return voList; } } + /** + * 递归构建多级组织机构树结构 + * + * @param currentNode 当前需要处理的组织机构节点 + * @param parentToChildrenMap 父节点ID到子节点列表的映射表(预处理结果,用于O(1)时间查找子节点) + * @param allDepartmentIdBuilder 记录所有层级部门ID的字符串构建器(按层级顺序累加) + * @apiNote 通过递归方式为当前节点设置子节点,并继续处理子节点的子节点,最终形成完整的多级树结构。 + * 依赖预处理的{@code parentToChildrenMap}提升查找子节点效率,避免重复遍历全量数据。 + */ + private void buildMultiLevelTree(SysOrgVO currentNode, + Map> parentToChildrenMap, + StringBuilder allDepartmentIdBuilder) { + // 从映射表直接获取当前节点的子节点(O(1)) + List children = parentToChildrenMap.getOrDefault(currentNode.getOrgId(), new ArrayList<>()); + + // 排序 + List sortedChildren = children.stream() + .sorted(Comparator.comparing(SysOrgVO::getSort, Comparator.nullsLast(String::compareTo))) + .collect(Collectors.toList()); + + currentNode.setChildren(sortedChildren); + + // 记录当前节点ID,累加所有层级ID + allDepartmentIdBuilder.append(",").append(currentNode.getOrgId()); + + // 递归处理子节点 + for (SysOrgVO child : sortedChildren) { + buildMultiLevelTree(child, parentToChildrenMap, allDepartmentIdBuilder); + } + } + @Override public Boolean insertByVo(SysOrgVO vo) { vo.setOrgId(PropertyUtils.getSnowflakeId()).setCreateDate(LocalDateTime.now()); @@ -165,37 +206,6 @@ public class SysOrgServiceImpl extends BaseServiceImpl imp .setKey(orgVO.getOrgId()) .setValue(orgVO.getOrgId()); } - /** - * 递归查询部门信息树形展示 - * - * @param sysOrgVOList 所有部门信息 - * @param sysOrg 当前查询节点 - */ - private void getChildrenNode(List sysOrgVOList, SysOrgVO sysOrg, String allDepartmentId) { - - List childrenNodeList = new ArrayList<>(); - - for (SysOrgVO sysOrgVO : sysOrgVOList) { - //判断机构部门上级ID和当前节点ID是否相等 - if (StringUtils.equals(sysOrg.getOrgId(), sysOrgVO.getUpOrgId())) { - childrenNodeList.add(sysOrgVO); - allDepartmentId += sysOrgVO.getOrgId(); - getChildrenNode(sysOrgVOList, sysOrgVO, allDepartmentId); - } - } - //判断是否有下级节点 - if (!CollectionUtils.isEmpty(childrenNodeList)) { - //根据sort排序 - childrenNodeList = childrenNodeList - .stream() - .map(this::setInfoForTree) - .sorted(Comparator.comparing(SysOrgVO::getSort, Comparator.nullsLast(String::compareTo))) - .collect(Collectors.toList()); - sysOrg.setChildren(childrenNodeList); - } else { - sysOrg.setChildren(ListUtil.empty()); - } - } private LambdaQueryWrapper buildQueryWrapper(SysOrgVO vo) { LambdaQueryWrapper lqw = Wrappers.lambdaQuery();