递归在多级数据结构中的简单应用

哈喽,我是小码,半年多没更新了,这段时间换了新工作,工作也很忙。后续会尽量多写点,坚持确实是一件很难,很酷的事情。最近在公司负责开发商品有关的开发,商品包含类型、款式等属性,而类型可能有一级类型、二级类型甚至是三级类型,针对这种多级分类,这就就不好使用简单的查询了。之前也写了一篇文章,Java递归实现评论多级回复,写的比较简单。本文做一些更加系统、完善的方案。

多级数据结构的场景

多级数据在电商或者后台管理系统中是比较常见,比如博客或者短视频的评论,人员系统的多级部门等等,

评论系统

A 写了一条评论,B 就可以回复 A 评论,C 又可以回复 B.

评论A
├── 评论B,回复A
│   └── 评论C,回复B
└── 评论D,回复A

人员系统

一般人员都是绑定一个企业和部门,企业有分公司,部门会多级部门。每个人员绑定一个部门.

选择部门之后就可以获取对应的人员列表信息。

商品的多级分类

商品的类型,会细分多个类型,有一级分类,二级分类,或者有多级分类,比如黄金,分成黄金精品,黄金精品又分成手镯、项链。手镯又分成固口手镯、开口手镯、卡扣手镯等等。

多级结构解决方案

像这种类似于树形结构的数据,数据一般都会包含idparent_idname等字段,通过idparent_id来关联数据。下面是一个简单的实体:

public class Multistage {

    public Multistage(Integer id,Integer parentId,String message) {
        this.id = id;
        this.parentId = parentId;
        this.message = message;
    }

    /**
     * id
     */
    private Integer id;

    /**
     * 父类id
     */
    private Integer parentId;

    /**
     * 名称
     */
    private String name;
    
    // 省略get、set

}


数据表和上面的实体类似。

1、展示多级接口

展示多级数据接口,就需要使用树的接口。类似下面的接口:

public class ViewMultistage {

    /**
     * id
     */
    private Integer id;

    /**
     * 父类id
     */
    private Integer parentId;

    /**
     * 名称
     */
    private String name;

    /**
     * 子集
     */
    private List<ViewMultistage> children = new ArrayList<>();

}

上面的几个例子,评论、部门、以及商品的分类,都是需要展示所有数据,所以需要从数据库获取所有数据,再使用代码归类。

针对这种多级、不确定层级数量的,一般都使用递归方法获取。从数据库获取到列表数据,使用递归方式转换:

// 数据库获取数据
List<Multistage> multistageList = "select * from t_xxxx";

// 树形结果
ViewMultistage root = new ViewMultistage();

// 添加首节点
root.setId(-1);
// 递归添加
add(root,multistageList);
// 结果
List<ViewMultistage> viewMultistageList = root.getChildren();
System.out.println(viewMultistageList);

// 递归添加数据
private void add(ViewMultistage rootViewMultistage, List<Multistage> multistageList) {
    for (Multistage multistage : multistageList) {
        if (rootViewMultistage.getId().equals(multistage.getParentId())) {
            ViewMultistage viewMultistage = new ViewMultistage();
            BeanUtils.copyProperties(multistage, viewMultistage);
            rootViewMultistage.getChildren().add(viewMultistage);
            add(viewMultistage, multistageList);
        }
    }
}

简略解释一下代码:

  • 获取数据列表,创建树形类。
  • 创建 -1 的虚拟节点,添加到属树形类上。
  • 使用递归不断找到子节点,直到遍历完所有数据。
  • 虚拟节点的子节点 root.getChildren() 就是我们要的结果。

从数据库获取的数据一定要有顺序,子数据不能比父数据排前面。

查询子集数据

如果不是获取所有的数据,只是获取一部分的数据。以部门和人员举例,部门有子部门,子部门有部门人员。要求查询部门以及子部门的人员信息。商品绑定二级款式或者三级款式,但是需要通过一级款式找到对应的下级的商品。

解决问题的重点就是获取到部门以及子部门的集合,这里就有两个方案。

获取所有部门,代码筛选

从数据获取所有的部门数据,遍历列表,筛选出符合条件的数据。比如上面的华南部门,假设 id 为 3,通过如下代码就能获取到部门 id 集合:

Integer id = 3;
Set<Integer> idSet = new HashSet<>();
idSet.add(id);
for (ViewMultistage multistage : viewMultistageList) {
    Integer parentId = multistage.getParentId();
    if (idSet.contains(parentId)) {
        idSet.add(multistage.getId());
    }
}

通过某个 id 就可以筛选部门以及子部门的集合,然后通过部门 id 的集合就能获取到人员信息。

但是如果只是获取一小部门的子集,却要获取全部数据,有点浪费查询资源。可以在数据库中刷选好数据,通过数据库递归获取数据。

通过数据库递归查找

查询数据大部分时候还是需要查询数据库,通过数据库一步到位,也减少了代码的的书写。将递归的查询方式转移到数据库中,使用到了 Mysql 递归函数 with recursive,用法如下:

WITH RECURSIVE family_tree AS (

    -- 基础查询:从给定的一级 id 开始
    SELECT
        id,
        parent_id
    FROM parents
    WHERE id = 1  -- 替换为你要查询的一级 id
    
    UNION ALL
    -- 递归查询:查找子节点
    SELECT
        p.id,
        p.parent_id
    FROM
        parents p
    INNER JOIN family_tree ft ON p.parent_id = ft.id

)

select tu.* from family_tree ft
left join t_user tu on tu.dept_id = ft.id

分析with recursive用法:

  • WITH RECURSIVE family_tree AS 是一个固定用法,将 () 查询的数据结果返回给 family_tree。
  • 函数体里面包含两部分,起始值循环值
    • 起始值:确认首节点的位置,上面例子以 id = 1作为起始值。
    • 循环值:以 id = 1 找到 parent_id 为 1 的数据,假设这个 id 为 2,然后找到 parent_id 的数据,一直循环查找,直到查询结束。
    • 上面的 family_tree 就类似通过父部门获取到所有的子部门,使用用户表关联,就能获取所有部门以及子部门的用户信息。

总结

多级数据结构在项目开发中是一种比较常见的数据结构,比如:

  • 评论,评论回复评论,其他评论再回复评论。
  • 企业部门,部门有子部门,或者公司有子公司。
  • 商品分类有一级分类,二级分类。

多级数据结构需要解决两个问题,一个是查询所有数据,另外一个是查询部分数据,这两个都需要使用到递归的查询。

  • 查询所有数据
    • 比较少的数据,就可以查询所有的数据,从数据库查询到所以数据,按照添加时间的先后排序,再使用递归的方式将数据组装成一个树形结构。
    • 如果是评论的数据,就需要存储评论的等级,先分页获取一级的评论,再通过一级评论获取下级评论。
  • 查询部分数据
    • 通过某个一级部门获取所有的子部门,有两种方式,第一种是获取所有的部门数据,再循环遍历数据,将符合的数据放到一个集合中。
    • 第二种是使用 Mysql 递归,使用with recursive 先确定一个起始值,在不断的遍历下级部门。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/686133.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MMU】——ARM 一级页表

文章目录 一级页表项即 entry 的格式如下 从上图可以看出 L1 页表项有四种可能类型 产生中止异常的故障条目。这可能是预取或数据中止、取决于访问类型。这实际上表示虚拟地址未映射 bit[1:0] = 00指向 L2 转换表的条目。这样就能将 1MB 的内存分页 bit[1:0] = 01。1MB 段转换…

【因果推断python】21_匹配2

目录 匹配估计器 匹配估计器 子分类估计器在实践中用得不多&#xff08;我们很快就会明白为什么&#xff0c;主要是因为维度诅咒这个原因&#xff09;&#xff0c;但它让我们很好地、直观地了解了因果推理估计器应该做什么&#xff0c;以及它应该如何控制混淆因素。这使我们能…

如何减少Apache Spark日志的数量

修改log4j配置文件&#xff0c;没有就创建&#xff1a; 内容&#xff1a; # 设置日志记录器 log4j.rootCategoryWARN, console log4j.appender.consoleorg.apache.log4j.ConsoleAppender log4j.appender.console.targetSystem.err log4j.appender.console.layoutorg.apache.lo…

什么是IDE?– 集成开发环境

IDE &#xff08;集成开发环境&#xff09;是将常用的开发人员工具组合到紧凑的 GUI&#xff08;图形用户界面&#xff09;应用程序中的软件。它是代码编辑器、代码编译器和代码调试器等工具与集成终端的组合。 为什么 IDE 很重要&#xff1f; 人们当然不需要 IDE来编码或开发…

cnPuTTY 0.81.0.1-JK—PuTTY 0.81中文JK补丁版的简单说明~~

原始补丁网站的链接&#xff1a;PuTTY for win32 storing configuration into file2. 6. 2024 - Update: this modified PuTTY is now based on PuTTY 0.81 (version 0.23.0) 本次官方正式发布的补丁与上一版本的补丁相同&#xff0c;无明显变化。关于JK补丁的信息也可以参考&…

企业微信hook接口协议,ipad协议http,内部联系人备注修改

内部联系人备注修改 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信 请求示例 {"uuid":"1688855749266556","vid":1688856554448765,"remark":"备注啦啦啦22222","des&quo…

每天五分钟深度学习:逻辑回归算法的单样本的梯度下降计算

本文重点 上节课我们已经知道了如何利用计算图通过链式法则来求解输出J对变量的梯度或者导数。本节课程我们将通过逻辑回归这一个具体的例子,来演示如何使用计算图完成逻辑回归的梯度下降算法。 逻辑回归 逻辑回归算法的目标函数,损失函数,代价函数,以及参数更新的方式如…

计算机网络学习记录 应用层 Day6

你好,我是Qiuner. 为记录自己编程学习过程和帮助别人少走弯路而写博客 这是我的 github https://github.com/Qiuner ⭐️ ​ gitee https://gitee.com/Qiuner &#x1f339; 如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 &#x1f604; (^ ~ ^) 想看更多 那就点个关注吧 我…

【Python报错】已解决AttributeError: Nonetype Object Has NoAttribute Group

解决Python报错&#xff1a;AttributeError: ‘list’ object has no attribute ‘get’ 在Python中&#xff0c;AttributeError通常表示你试图访问的对象没有你请求的属性或方法。如果你遇到了AttributeError: list object has no attribute get的错误&#xff0c;这通常意味着…

苹果Vision Pro 界面中英翻译

目录 菜单 &#x1f537;General&#x1f504;一般 AirDrop 隔空投送 Background App Refresh 后台应用刷新 Keyboards 键盘 VPN & Device Management VPN与设备管理​编辑Legal & Regulatory 法律法规 &#x1f537;Apps&#x1f504;应用程序 &#x1f537;Pe…

【python/pytorch】已解决ModuleNotFoundError: No module named ‘torch‘

【PyTorch】成功解决ModuleNotFoundError: No module named torch 一、引言 在深度学习领域&#xff0c;PyTorch作为一款强大的开源机器学习库&#xff0c;受到了众多研究者和开发者的青睐。然而&#xff0c;在安装和使用PyTorch的过程中&#xff0c;有时会遇到一些问题和挑战…

关于python包导入问题的重思考

将顶层目录直接设置为一个包 像这样&#xff0c;每一个文件从顶层包开始导入 这样可以解决我的问题&#xff0c;但是要注意的时&#xff0c;要避免使用出现上下级出现同名包的情况&#xff0c;比如&#xff1a; AutoServer--AutoServer--__init__.py--__init__.py这种情况下…

双指针问题1

文章目录 1. 移动零&#xff08;283&#xff09;2. 复写零&#xff08;1089&#xff09;3. 快乐数&#xff08;202&#xff09;4. 盛最多水的容器&#xff08;11&#xff09; 1. 移动零&#xff08;283&#xff09; 题目描述&#xff1a; 算法原理&#xff1a; 设置两个指针…

Centos7安装ElasticSearch

Centos7安装ElasticSearch 准备工作 下载elasticsearch https://www.elastic.co/cn/elasticsearch 将下载好的包上传到/usr/local/elasticsearch/ 路径下 安装 安装elasticsearch解压缩即可&#xff01; tar -zxvf elasticsearch-8.12.2-linux-x86_64.tar.gz进入/usr/loca…

计算机毕业设计PySpark+Hadoop地震预测系统 地震数据分析可视化 地震爬虫 大数据毕业设计 Flink Hadoop 深度学习

基于Hadoop的地震预测的 分析与可视化研究 姓 名&#xff1a;____田伟情_________ 系 别&#xff1a;____信息技术学院___ 专 业&#xff1a;数据科学与大数据技术 学 号&#xff1a;__2011103094________ 指导教师&#xff1a;_____王双喜________ 年 月 日 …

度安讲 | 第二期「安全左移·业务护航」技术沙龙成功举办

当下&#xff0c;“安全左移”作为落地DevSecOps的重要实践之一&#xff0c;已在业界达成共识。DevSecOps作为一种集开发、安全、运维于一体的软件开发和运营模式&#xff0c;强调在敏捷交付下&#xff0c;“安全”在软件开发生命周期的全覆盖贯穿和核心位置。所谓“安全左移”…

多线程..

线程定义&#xff1a;线程是操作系统能够进行运算调度的最小单位&#xff0c;它被包含在进程之中&#xff0c;是进程中实际运作单位。简单来说&#xff0c;应用软件中相互独立&#xff0c;可以同时运作的功能。 多线程作用&#xff1a;有了多线程&#xff0c;我们就可以让程序…

03-240605-Spark笔记

03-240605 1. 行动算子-1 reduce 聚合 格式: def reduce(f: (T, T) > T): T 例子&#xff1a; val sparkConf new SparkConf().setMaster("local[*]").setAppName("Operator")val sc new SparkContext(sparkConf) ​val rdd sc.makeRDD(List(1…

MySQL第二种实现方式:现在有一个生产计划,甲乙丙3个品类共16个产品,生产时间6天,每天甲品类可以生产1张单,乙3张,丙1张,请用MySQL写出H列的效果

接上篇&#xff1a;链接: 现在有一个生产计划&#xff0c;甲乙丙3个品类共16个产品&#xff0c;生产时间6天&#xff0c;每天甲品类可以生产1张单&#xff0c;乙3张&#xff0c;丙1张&#xff0c;请用MySQL写出H列的效果 第二种写法&#xff1a; -- 使用WITH子句创建CTE WITH…

【Python报错】已解决ImportError: cannot import name ‘mapping‘ from ‘collections‘

成功解决“ImportError: cannot import name ‘mapping’ from ‘collections’”错误的全面指南 成功解决“ImportError: cannot import name ‘mapping’ from ‘collections’”错误的全面指南 一、引言 在Python编程中&#xff0c;当我们尝试从某个模块中导入某个名称时&…