1. 二级树数据结构
2. 结构组装
// 创建一级和二级的实体类 @Data public class TwoSubject { private String id; private String title; }
@Data public class OneSubject { private String id; private String title; //一个一级分类有多个二级分类 private List<TwoSubject> children = new ArrayList<>(); }
//课程分类列表(树形) @GetMapping("getAllSubject") public R getAllSubject() { //list集合泛型是一级分类 List<OneSubject> list = eduSubjectService.getAllOneTwoSubject(); return R.ok().data("list",list); }
@Override public List<OneSubject> getAllOneTwoSubject() { //1. 查询一级目录 QueryWrapper<EduSubject> wrapperOne = new QueryWrapper<>(); wrapperOne.eq("parent_id","0"); List<EduSubject> oneSubjectList = baseMapper.selectList(wrapperOne); //2. 查询二级目录 QueryWrapper<EduSubject> wrapperTwo = new QueryWrapper<>(); wrapperTwo.ne("parent_id",0); List<EduSubject> twoSubjectList = baseMapper.selectList(wrapperTwo); List<OneSubject> finalSubjectList = new ArrayList<>(); //3. 封装一级 oneSubjectList.forEach(o->{ OneSubject oneSubject = new OneSubject(); BeanUtils.copyProperties(o,oneSubject); finalSubjectList.add(oneSubject); List<TwoSubject> twoFinalSubjectList = new ArrayList<>(); //4. 封装二级 twoSubjectList.forEach(t->{ if (t.getParentId().equals(o.getId())){ TwoSubject twoSubject = new TwoSubject(); BeanUtils.copyProperties(t,twoSubject); twoFinalSubjectList.add(twoSubject); } }); oneSubject.setChildren(twoFinalSubjectList); }); return finalSubjectList; }
3. 使用swagger测试
{ "success": true, "code": 20000, "message": "成功", "data": { "list": [ { "id": "1178214681118568449", "title": "后端开发", "children": [ { "id": "1178214681139539969", "title": "Java" }, { "id": "1178585108407984130", "title": "Python" } ] }, { "id": "1178214681181483010", "title": "前端开发", "children": [ { "id": "1178214681210843137", "title": "JavaScript" }, { "id": "1178585108454121473", "title": "HTML/CSS" } ] }, { "id": "1178214681231814658", "title": "云计算", "children": [ { "id": "1178214681252786178", "title": "Docker" }, { "id": "1178214681294729217", "title": "Linux" } ] }, { "id": "1178214681324089345", "title": "系统/运维", "children": [ { "id": "1178214681353449473", "title": "Linux" }, { "id": "1178214681382809602", "title": "Windows" } ] }, { "id": "1178214681399586817", "title": "数据库", "children": [ { "id": "1178214681428946945", "title": "MySQL" }, { "id": "1178214681454112770", "title": "MongoDB" } ] }, { "id": "1178214681483472898", "title": "大数据", "children": [ { "id": "1178214681504444418", "title": "Hadoop" }, { "id": "1178214681529610242", "title": "Spark" } ] }, { "id": "1178214681554776066", "title": "人工智能", "children": [ { "id": "1178214681584136193", "title": "Python" } ] }, { "id": "1178214681613496321", "title": "编程语言", "children": [ { "id": "1178214681626079234", "title": "Java" } ] } ] } }
4. 三级树结构封装
(1)组装结构
@Data @TableName("pms_category") public class CategoryEntity implements Serializable { private static final long serialVersionUID = 1L; /** * 分类id */ @TableId private Long catId; /** * 分类名称 */ private String name; /** * 父分类id */ private Long parentCid; /** * 层级 */ private Integer catLevel; /** * 是否显示[0-不显示,1显示] */ private Integer showStatus; /** * 排序 */ private Integer sort; /** * 图标地址 */ private String icon; /** * 计量单位 */ private String productUnit; /** * 商品数量 */ private Integer productCount; @TableField(exist = false) List<CategoryEntity> children; }
@RequestMapping("/list/tree") //@RequiresPermissions("product:category:list") public R list(@RequestParam Map<String, Object> params){ List<CategoryEntity> entities = categoryService.listWithTree(); return R.ok().put("data", entities); }
@Override public List<CategoryEntity> listWithTree() { //1、查出所有分类 List<CategoryEntity> entities = baseMapper.selectList(null); //2、组装成父子的树形结构 List<CategoryEntity> list = entities.stream().filter(categoryEntity -> categoryEntity.getParentCid() == 0) .map(menu -> { menu.setChildren(getChildren(menu, entities)); return menu; }) .sorted((m1, m2) -> { return (m1.getSort() == null ? 0 : m1.getSort()) - (m2.getSort() == null ? 0 : m2.getSort()); }).collect(Collectors.toList()); return list; } private List<CategoryEntity> getChildren(CategoryEntity menu, List<CategoryEntity> all) { List<CategoryEntity> childrenList = all.stream().filter(categoryEntity -> categoryEntity.getParentCid() == menu.getCatId()) .map(m -> { //1. 找到子菜单 m.setChildren(getChildren(m, all)); return m; }).sorted((m1, m2) -> { //2、菜单的排序 return (m1.getSort() == null ? 0 : m1.getSort()) - (m2.getSort() == null ? 0 : m2.getSort()); }).collect(Collectors.toList()); return childrenList; }
测试结果
5. hutool工具TreeUtil
https://doc.hutool.cn/pages/TreeUtil/#%E4%BB%8B%E7%BB%8D
6. 使用子id查询父id
在实现类中传入子id,使用递归查询
@Override public Long[] findCatelogPath(Long catelogId) { List<Long> paths = new ArrayList<>(); List<Long> parentPath = findParentPath(catelogId, paths); Collections.reverse(parentPath); return parentPath.toArray(new Long[parentPath.size()]); } private List<Long> findParentPath(Long catelogId,List<Long> paths){ //1、收集当前节点id paths.add(catelogId); CategoryEntity byId = this.getById(catelogId); if(byId.getParentCid()!=0){ findParentPath(byId.getParentCid(),paths); } return paths; }
测序结果
@Test public void contextLoads() { Long[] catelogPath = categoryService.findCatelogPath(165L); log.info("完整路径,{}", Arrays.asList(catelogPath)); }
完整路径,[1, 22, 165]