使用场景,不管是在前后端分离或者是不分离的项目中,我们通常会遇到这种多级分类的情况,比如前端需要选择 省——市——县 或者 计算机类——后端——Java工程师,这样的三级分类,也可能是二级分类或者更高级的分类。
下面我例举三级学科分类作为例子:
首先建表:
其中 id 代表当前学科,sub_parent_id 代表当前学科的父类学科,当值为 0 时表示当前是一级学科,即没有父类学科,至于 sub_class 和 sub_number 分别表示学科等级和代码,这两个可有可无,至于定义什么样的属性取决于如何更好的进行前后端交互。
接下来我将展示用 递归 方法结合 lambda 中的 stream 流实现多级分类
下面是表的部分数据展示,注意:数据的 id 和父类 id 必须有关联;
接着是创建和学科代码表对应的实体类:
@Data
@EqualsAndHashCode(callSuper = false)
@TableName(“subject”)
@ApiModel(value=“Subject对象”, description=“”)
public class Subject implements Serializable {
private static final long serialVersionUID=1L;
private Integer id;
@ApiModelProperty(value = "学科名称")
private String subName;
@ApiModelProperty(value = "父类学科,为0就是一级学科")
private Integer subParentId;
@ApiModelProperty(value = "等级分类")
private Integer subClass;
@ApiModelProperty(value = "学科代码")
private String subNumber;
@TableField(exist = false)
private List<Subject> children;
}
注意实体类中最后一个地方:
@TableField(exist = false) 表示不和数据库中的字段对应,这里只是为了存放子分类。
@TableField(exist = false)
private List children;
下面是接口的编写:
@ApiOperation(value = "学科代码树")
@GetMapping("getSubject")
public CommonResult getSubject(){
//获取所有分类学科
List<Subject> subject = subjectService.listWithTree();
return CommonResult.success(subject);
}
接下来就是实现类,即最核心的部分,接口实现类代码之递归实现:
@Override
public List<Subject> listWithTree() {
List<Subject> entities = list();
List<Subject> subjectVOS = entities.stream().map(subject -> {
Subject subjectVO = new Subject();
BeanUtils.copyProperties(subject, subjectVO);
return subjectVO;
}).collect(Collectors.toList());
List<Subject> list = subjectVOS.stream().filter(subjectVO ->
subjectVO.getSubParentId()==0
).map((menu)->{
menu.setChildren(getChildrenData(menu,subjectVOS));
return menu;
}).collect(Collectors.toList());
return list;
}
//获取孩子(下级目录)的方法,递归实现
private List<Subject> getChildrenData(Subject root, List<Subject> all) {
List<Subject> children = all.stream().filter(subjectVO ->
subjectVO.getSubParentId().equals(root.getId())
).map(subjectVO -> {
subjectVO.setChildren(getChildrenData(subjectVO,all));
return subjectVO;
}).collect(Collectors.toList());
return children;
}
filter 是 lambda 中用于获取条件内的数据的写法,先获取所有 parentId 为0 ,即一级分类的数据,然后通过递归的方式获取所有子分类
其中 map 是 lambda 中的写法,用于封装数据