递归查询树形结构数据

最近做一个网上的在线教育项目涉及树形结构数据展示,教程里使用建多个实体类分别查询并封装来展示,这样做对于两级树形结构还好说,如果对于多层树形结构来看就不太合适了。这里我用的是递归查询来展示,记录一下。

1.先贴图excel数据(这里通过excel录入表数据,只使用了三层结构,多层也适用):

表数据(parent_id为0的是一级分类,顶层数据):

2.对应实体类表数据实体类:

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="EduSubject对象", description="课程科目")
public class EduSubject implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "课程类别ID")
    @TableId(value = "id", type = IdType.ID_WORKER_STR)
    private String id;

    @ApiModelProperty(value = "类别名称")
    private String title;

    @ApiModelProperty(value = "父ID")
    private String parentId;

    @ApiModelProperty(value = "排序字段")
    private Integer sort;

    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private Date gmtCreate;

    @ApiModelProperty(value = "更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmtModified;


}

3.返回页面的实体类vo

@Data
@NoArgsConstructor
@AllArgsConstructor
public class EduSubjectVo {

    private String id;
    private String parentId;
    private String title;
    private List<EduSubjectVo> children;

}

 4.Controller接口,service接口

@ApiOperation(value = "查询分类树形列表")
@PostMapping("/findSubjectTreeList")
public JsonResult findSubjectTreeList() {
      List<EduSubjectVo> eduSubjectVoList = eduSubjectService.findSubjectTreeList();
      return JsonResult.success(eduSubjectVoList);
}

List<EduSubjectVo> findSubjectTreeList();

5.实现类核心方法

    @Override
    public List<EduSubjectVo> findSubjectTreeList() {

        // 最终返回结果
        List<EduSubjectVo> resultList = new ArrayList<>();

        // 查询所有课程分类并转换
        List<EduSubjectVo> allSubjectVoList = new ArrayList<>();
        List<EduSubject> list = this.list(null);
        for (EduSubject eduSubject : list) {
            EduSubjectVo eduSubjectVo = new EduSubjectVo();
            BeanUtils.copyProperties(eduSubject, eduSubjectVo);
            allSubjectVoList.add(eduSubjectVo);
        }

        // 过滤一级分类
        for (EduSubjectVo subjectVo : allSubjectVoList) {
            if (Objects.deepEquals(subjectVo.getParentId(), "0")) {
                getChildSubjectList(subjectVo, allSubjectVoList);
                resultList.add(subjectVo);
            }
        }

        return resultList;
    }

    private void getChildSubjectList(EduSubjectVo eduSubjectVo, List<EduSubjectVo> 
    eduSubjectVoList) {

        // 过滤子节点,如果子节点不为空,开始递归查询所有节点,直到子节点为空停止
        List<EduSubjectVo> children = eduSubjectVoList.stream().filter(e -> Objects.deepEquals(e.getParentId(), eduSubjectVo.getId())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(children)) {
            for (EduSubjectVo child : children) {
                getChildSubjectList(child, eduSubjectVoList);
            }
            eduSubjectVo.setChildren(children);
        }

    }

这样就一次递归查询出所有树形数据并封装返回了

6.页面渲染效果

7.小结 

对于分层结构多但是数据量不是很大的情况下,可以用递归查询这种方式,简便快捷,不存在什么效率问题。但是对于数据量大且分层又多的情况,这种就不是很合适了(效率会比较低),这种情况就适合用懒加载的方式查询和渲染,即点一层调一次查询。

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
/** * 根据等级查询类目树 * * @param level * @return */ @Override public List queryCategoryTree(Integer level) { //查询当前级别下类目 List list = categoryDAO.list(level); //组装好的类目树,返回前端 List categoryTree = new ArrayList(); //所有类目 List allDTOList = new ArrayList(); if (CollectionUtils.isEmpty(list)) { return categoryTree; } for (CategoryDO categoryDO : list) { allDTOList.add(new CategoryTreeDTO().convertDOToDTO(categoryDO)); } //当前等级类目 categoryTree = allDTOList.stream().filter(dto -> level.equals(dto.getLevel())).collect(Collectors.toList()); for (CategoryTreeDTO categoryTreeDTO : categoryTree) { //组装类目为树结构 assembleTree(categoryTreeDTO, allDTOList,Constants.CATEGORY_MAX_LEVEL - level); } return categoryTree; } /** * 组装树 * * @param categoryTreeDTO * @param allList * @param remainRecursionCount 剩余递归次数 * @return */ public CategoryTreeDTO assembleTree(CategoryTreeDTO categoryTreeDTO, List allList, int remainRecursionCount) { remainRecursionCount--; //最大递归次数不超过Constants.CATEGORY_MAX_LEVEL-level次,防止坏数据死循环 if(remainRecursionCount < 0){ return categoryTreeDTO; } String categoryCode = categoryTreeDTO.getCategoryCode(); Integer level = categoryTreeDTO.getLevel(); //到达最后等级树返回 if (Constants.CATEGORY_MAX_LEVEL == level) { return categoryTreeDTO; } //子类目 List child = allList.stream().filter(a -> categoryCode.equals(a.getParentCode())).collect(Collectors.toList()); if (null == child) { return categoryTreeDTO; } categoryTreeDTO.setChildren(child); //组装子类目 for (CategoryTreeDTO dto : child) { assembleTree(dto, allList,remainRecursionCount); } return categoryTreeDTO; }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值