【Java】实现无限下级动态树形结构数据


前言

在项目中经常遇到做树形结构的需求,但是可能会有很多种情况不同形式的树形结构,最常见的就是有id,父id,名称这种做树形结构,会比较好做。但是我这边遇到的是单列数据ID,例如最高级id是01,01的下级是0101,0102这种形式的树形结构,可以参考下我是如何实现的;并且是无限下级

我这边用的是SpringCloud+MyBatisPuls

一、表结构以及所需用到的实体

1.数据库表

这边的sCode就是数据ID,最高级是两位数01、02、03,第二级就是0101、0202、0303这种形式;

在这里插入图片描述

2.数据库表对应Model

package com.whxx.emr.template.bean;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.Data;

/**
 * @author 孤巷.
 * @description 
 * @date  2024/4/1 上午 8:58
 */
/**
 * 电子病历目录
 */
@ApiModel(description="电子病历目录")
@Data
@TableName(value = "emr_listroot")
public class EmrListroot {
    /**
     * 文件代码
     */
    @TableId(value = "sCode", type = IdType.AUTO)
    @ApiModelProperty(value="文件代码")
    private String scode;

    /**
     * 文件名称
     */
    @TableField(value = "sNote")
    @ApiModelProperty(value="文件名称")
    private String snote;

    /**
     * 在用(0否1是)
     */
    @TableField(value = "sOpen")
    @ApiModelProperty(value="在用(0否1是)")
    private String sopen;

    /**
     * 运行病历顺序
     */
    @TableField(value = "nRun")
    @ApiModelProperty(value="运行病历顺序")
    private BigDecimal nrun;

    /**
     * 归档病历顺序
     */
    @TableField(value = "nStore")
    @ApiModelProperty(value="归档病历顺序")
    private BigDecimal nstore;

    /**
     * 登记时间
     */
    @TableField(value = "dTime")
    @ApiModelProperty(value="登记时间")
    private LocalDateTime dtime;
}

3.最终的树形结构DTO(返回给前端的实体)

备注:patientId和children是我自己加进去的,用来组装树形结构数据

package com.whxx.emr.template.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

/**
 * @author 孤巷.
 * @description
 * @date 2024/4/1 上午 9:10
 */
@Data
public class ListRootTreeViewDto {

    @ApiModelProperty(value = "目录编码")
    private String scode;
    @ApiModelProperty(value = "目录名称")
    private String snote;
    @ApiModelProperty(value = "目录父级编码")
    private String patientId;
    @ApiModelProperty(value = "目录子节点")
    private List<ListRootTreeViewDto> children;

    public ListRootTreeViewDto(String scode, String snote, String patientId, List<ListRootTreeViewDto> children) {
        this.scode = scode;
        this.snote = snote;
        this.patientId = patientId;
        this.children = children;
    }
}

二、业务代码

1.递归填充所有子节点

代码如下:

    private void createResourceClassTreeType2(List<ListRootTreeViewDto> parentList,Map<String,List<ListRootTreeViewDto>> tempMap){
        for (ListRootTreeViewDto parent : parentList) {
            List<ListRootTreeViewDto> children = tempMap.get(parent.getScode());
            if( children != null ){
                parent.setChildren(children);
                createResourceClassTreeType2(children, tempMap);
            }
        }
    }

2.获取树状结构数据数据-无限下级

代码如下(示例):

    public List<ListRootTreeViewDto> getResourceClassTreeType2(List<ListRootTreeViewDto> allList) {
        List<ListRootTreeViewDto> parentList = new ArrayList<>();
        //获取所有父类集合
        for(ListRootTreeViewDto dto : allList){
            if(dto.getPatientId().equals("0")){
                parentList.add(dto);
            }
        }
        //  以 父id 为 KEY ,
        Map<String, List<ListRootTreeViewDto>> tempMap = new HashMap<>();
        String resourceClassParentId;
        List<ListRootTreeViewDto> children;
        for (ListRootTreeViewDto classTemp : allList) {
            resourceClassParentId = classTemp == null ? null : classTemp.getPatientId();
            if( resourceClassParentId == null ){
                continue;
            }
            children = tempMap.get(resourceClassParentId);
            if( children == null ){
                children = new LinkedList<>();
                children.add(new ListRootTreeViewDto(classTemp.getScode(), classTemp.getSnote(), classTemp.getPatientId(),classTemp.getChildren()));
                tempMap.put(resourceClassParentId, children);
            } else {
                children.add(new ListRootTreeViewDto(classTemp.getScode(), classTemp.getSnote(), classTemp.getPatientId(),classTemp.getChildren()));
            }
        }
        //  填充子节点 并 返回
        createResourceClassTreeType2(parentList, tempMap);
        return parentList;
    }

3.最后组装的Service

提示:Result 这个类是我通用的返回类,你也可以根据你自己的需求来;treeViewList 就是最后的树形结构结果了,返回给前段就行!

    /**
     * 获取病历模板目录-树状结构
     * @return Result
     */
    public Result<List<ListRootTreeViewDto>> getListRootTreeView(){
        LambdaQueryWrapper<EmrListroot> lambda = new LambdaQueryWrapper<>();
        lambda.eq(EmrListroot::getSopen,1);
        lambda.orderByAsc(EmrListroot::getScode);
        //查询所有目录信息
        List<ListRootTreeViewDto> emrKeyTitleVoList = new ArrayList<>();
        List<EmrListroot> list = list(lambda);
        //编辑数据,赋值父ID(我这表里没有父ID,所以要自己组装赋值下父id,有父id的跳过这一步就可以)
        for (EmrListroot emrListroot : list){
            ListRootTreeViewDto dto = new ListRootTreeViewDto(emrListroot.getScode(),emrListroot.getSnote(),null,new ArrayList<>());
            if(emrListroot.getScode().length() == 2){
                dto.setPatientId("0");
            }else{
                String code = dto.getScode();
                //我这边因为是01、02、03的形式的id,截取最后两位,前面的就是这条数据的父ID了
                String parentId = code.substring(0,code.length() - 2);
                dto.setPatientId(parentId);
            }
            emrKeyTitleVoList.add(dto);
        }
        List<ListRootTreeViewDto> treeViewList = getResourceClassTreeType2(emrKeyTitleVoList);
        return Result.success(treeViewList);
    }

总结

看到这里相信你已经实现了树形结构了,后期我会记录更多编写项目中遇到的技术点和问题,欢迎你的关注,有啥不清楚的可以下方评论或私信,我会第一时间回复哦!!!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值