My Life My Dream!

守信 求实 好学 力行
随笔 - 193, 文章 - 0, 评论 - 55, 阅读 - 34万
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

        产品或项目开发过程中,经常遇到一些存在上下级关系的树形结构,但在数据库中存储为二维表关系数据的情况。而前端树形控件又要求按照树形层级组织数据,这就存在一个平铺的关系数据转换为树形层级结构的典型问题。

       表结构及二维数据示例(以id,parentid自关联为例):

Create Table TreeData(id varchar(36), code varchar(50), name narchar(100), parentid varchar(36));

[{id: "", code: "", name: "", parentid: ""}]

 

       期望的数据示例:

 

复制代码
[{
        id: "",
        code: "",
        name: "",
        parentid: "",
        subNodes: [{
                id: "",
                code: "",
                name: "",
                parentid: "",
                subNodes: []
            }
        ]
    }
]
复制代码

 

       在实际编码过程,我们可以采用嵌套循环或递归等方式处理,但如果遇到数据量较大、层级较深且层级不固定等场景,此种实现性能不佳。从时间复杂度来说,是O(n2).

       之前在几次性能优化时,采用过一个方法,先构造全量数据的HashMap,然后再快速将自身加到父对象的子节点集合,此方式性能稳定、时间复杂度为O(n),经过实际验证效果也不错(5k节点时间消耗从>700ms优化到<100ms),在此记录备忘。

复制代码
import lombok.Data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
public class Func {
    private String id;
    private String code;
    private String name;
    private String parentId;
    private List<Func> subNodes;

    public List<Func> BuildTreeData(List<Func> orignList) {
        Map<String, Func> allMap = new HashMap<>();
        List<Func> rootList = new ArrayList<>();
        for (Func func : orignList) {
            allMap.put(func.getId(), func);
        }

        for (Map.Entry<String, Func> map : allMap.entrySet()) {
            if (allMap.containsKey(map.getValue().getParentId())) {
                Func parent = allMap.get(map.getValue().getParentId());
                if (parent.getSubNodes() == null) {
                    parent.setSubNodes(new ArrayList<>());
                }
                parent.getSubNodes().add(map.getValue());
            } else {
                rootList.add(map.getValue());
            }
        }

        return rootList;
    }
}
复制代码

 

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2020-07-30 JVM启动参数建议
2020-07-30 Linux环境jcmd抓取进程信息及内存dump
2020-07-30 Linux常用基础命令
点击右上角即可分享
微信分享提示