一.应用场景
有时候需要我们后台给前台传树结构的数据,要怎么查询? 怎么返回数据呢?
二.数据库表设计以及数据内容(以部门举例)
id 主键
parent_id 父级部门id
depart_name 部门名词
sort 部门排序
三.实体类
@Data
public class KunKun implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("部门id")
private String id;
@ApiModelProperty("父级部门id")
private String parentId;
@ApiModelProperty("机构/部门名称")
private String departName;
@ApiModelProperty("子级部门的集合")
private List<KunKun> children;
}
四.代码实现
public void selectKunTree() {
//查询部门信息,获取全部部门信息
List<KunKun> kunList = xxxxMapper.selectList() ;
//组装成树形结构
//找到所有的一级分类(也就是树的根节点)
List<KunKun> ikuns = kunList.stream().filter(ikun ->
ikun.getParentId() == 0
).map((menu) -> {
menu.setChildren(getChildrens(menu,kunList));
return menu;
}).sorted((menu1,menu2)-> {//如果你查询的时候就排好序了就不用写这里
return menu1.getSort() - menu2.getSort();
}).collect(Collectors.tolist());
//返回树结构的list
return ikuns;
}
//递归方法
private List<KunKun> getChildrens(KunKun root,List<KunKun> all){
List<KunKun> children = all.stream().filter(ikun -> {
return ikun.getParentId() == root.getId();
}).map(ikun -> { //找子部门
ikun.setChildren(getChildrens(ikun ,all));
return categoryEntity;
}).sorted( (menu1 ,menu2)
return menu1.getSort - menu2.getSort()
}).collect(Collectors .tolist());
return children;
}
=========================
多个一级id场景
实现思路
获取所有的分类。
获取所有分类的id集合。使用stream()实现,stream使用教程
获取一级分类信息。同样使用stream()实现。
循环一级分类,在循环中将一级分类添加子分类,并且将一级分类加入返回的树结构中(备注:不加入返回的树结构中也行,直接返回步骤3的分类信息一样)。
重点是步骤4中将一级分类添加子分类,并且子分类在添加子子分类,子子分类再添加子子子分类··········等等,实现过程使用递归即可。
步骤5的实现过程:写一个递归方法,往当前节点添加子节点,首先获取当前节点的字节点集合,然后把这个集合放入到当前节点子节点属性中,接着再次调用当前递归的方法,把刚获取到的子节点当成新当前节点,获取新当前节点的新子节点,注意再次调用当前递归的方法,把刚获取到的子节点当成新当前节点之前首先判断新当前节点有没有子节点(判断方法:获取当前节点的字节点数组,根据数组的size()>0?判断是否有子节点),如果没有就不用递归。
总结:1-4是数据准备,5-6是实现递归(当前节点添加子节点的递归)。
代码展示
- 主要思路代码
@GetMapping("/list")
public Result list() {
//所有的分类
List<Category> categoryList = categoryService.list();
//所有分类id集合
List<String> idList = categoryList.stream().map(Category::getId).collect(Collectors.toList());
//返回的树分类结果
List<Category> treeCategory = new ArrayList<>();
//一级分类目录
List<Category> categories = categoryList.stream().filter(category -> !idList.contains(category.getParentId())).collect(Collectors.toList());
//循环当前一级分类目录
for (Category category : categories) {
//给当前分类节点 添加 子分类节点
addChild(categoryList,category);
//当前分类添加完子节点分类之后,添加到返回的树结构中
treeCategory.add(category);
}
//把返回的树结构返回
return Result.success(categories);
}
/**
* 给当前分类节点 添加 子分类节点
* @param categoryList 所有的分类
* @param category 当前分类节点
*/
public void addChild( List<Category> categoryList,Category category){
//循环所有的分类,获取当前节点的所有子节点
List<Category> categoryListChild = categoryList.stream().filter(category1 -> category1.getParentId().equals(category.getId())).collect(Collectors.toList());
//把当前分类的子节点添加到当前分类
category.setChildList(categoryListChild);
//再次调用本方法,把当前节点的子节点当成当前节点,继续添加子节点,备注:这样会造成一直循环
categoryListChild.forEach(category1 -> {
//添加一步,判断当前节点是否有子节点,没有就不循环递归
if (haveChild(categoryList,category1)){
addChild(categoryList,category1);
}
});
}
/**
* 判断当前节点 是否存在 子节点
* @param categoryList 所有的分类
* @param category 当前节点
*/
public boolean haveChild( List<Category> categoryList,Category category){
//获取当前节点的子节点
List<Category> categoryListChild = categoryList.stream().filter(category1 -> category1.getParentId().equals(category.getId())).collect(Collectors.toList());
//子节点大于0则存在,否则不存在
return categoryListChild==null&&categoryListChild.size()>0;
- 实体类代码展示
备注:实体类代码中一定要有一个子节点数组。实体类对用最上面的实体类图片
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ID_WORKER_STR)
private String id;
/**
* 类别名称
*/
private String name;
/**
* 上级id
*/
private String parentId;
/**
* 分类级别
*/
private Integer type;
/**
* 子节点数组
*/
@TableField(exist = false)
private List<Category> childList;
}
##吧数据处理返回:
{
"code": 200,
"msg": "操作成功",
"data": [
{
"id": "1",
"name": "电子产品",
"parentId": "0",
"type": 1,
"childList": [
{
"id": "5",
"name": "笔记本电脑",
"parentId": "1",
"type": 2,
"childList": [
{
"id": "21",
"name": "联想笔记本",
"parentId": "5",
"type": 3,
"childList": []
},
{
"id": "22",
"name": "外星人笔记本",
"parentId": "5",
"type": 3,
"childList": []
},
{
"id": "23",
"name": "戴尔笔记本",
"parentId": "5",
"type": 3,
"childList": []
}
]
},
{
"id": "6",
"name": "手机",
"parentId": "1",
"type": 2,
"childList": [
{
"id": "24",
"name": "苹果手机",
"parentId": "6",
"type": 3,
"childList": []
},
{
"id": "25",
"name": "菠萝手机",
"parentId": "6",
"type": 3,
"childList": []
}
]
},
{
"id": "7",
"name": "耳机",
"parentId": "1",
"type": 2,
"childList": []
},
{
"id": "8",
"name": "电子烟",
"parentId": "1",
"type": 2,
"childList": []
}
]
},
{
"id": "2",
"name": "生活用品",
"parentId": "0",
"type": 1,
"childList": [
{
"id": "10",
"name": "椅子",
"parentId": "2",
"type": 2,
"childList": []
},
{
"id": "11",
"name": "床",
"parentId": "2",
"type": 2,
"childList": []
},
{
"id": "19",
"name": "牙膏",
"parentId": "2",
"type": 2,
"childList": []
},
{
"id": "20",
"name": "牙刷",
"parentId": "2",
"type": 2,
"childList": []
},
{
"id": "9",
"name": "桌子",
"parentId": "2",
"type": 2,
"childList": []
}
]
},
{
"id": "3",
"name": "卫生用品",
"parentId": "0",
"type": 1,
"childList": [
{
"id": "12",
"name": "卫生纸",
"parentId": "3",
"type": 2,
"childList": []
},
{
"id": "13",
"name": "湿巾",
"parentId": "3",
"type": 2,
"childList": []
}
]
},
{
"id": "4",
"name": "学习用品",
"parentId": "0",
"type": 1,
"childList": [
{
"id": "14",
"name": "电子书",
"parentId": "4",
"type": 2,
"childList": []
},
{
"id": "15",
"name": "听力光盘",
"parentId": "4",
"type": 2,
"childList": []
},
{
"id": "16",
"name": "实体书",
"parentId": "4",
"type": 2,
"childList": []
},
{
"id": "17",
"name": "钢笔",
"parentId": "4",
"type": 2,
"childList": []
},
{
"id": "18",
"name": "笔记本子",
"parentId": "4",
"type": 2,
"childList": []
}
]
}
]
}