一 场景:假如有如下树形结构,V0到v14都为schoolVO,分别都有老师1位,学生2位,要求逐层(包括自身值)统计出每层的树节点都有总共多少名老师和学生,比如v11的结果等于v11自身+v13+v14
二 设计过程:
1 创建学校实例
@Data
@Builder
public class SchoolVO {
//教师人数
private Integer teacherNum;
//学生人数
private Integer studentNum;
//学校名称
private String name;
//子级school
private List<SchoolVO> subSchoolVOList;
}
2 单字段汇总实现方法,比如单独汇总出学生多少人和老师多少人(以下是独立汇总老师数量的实现)
int statisticslBySign(SchoolVO SchoolVO) {
List<SchoolVO> SchoolVOList = SchoolVO.getSubSchoolVOList();
if (SchoolVOList == null) {
return SchoolVO.getTeacherNum();
}
int sum = SchoolVO.getTeacherNum();
for (SchoolVO SchoolVO1 : SchoolVOList) {
sum = sum + statisticslBySign(SchoolVO1);
}
SchoolVO.setTeacherNum(sum);
return sum;
}
3 单字段汇总会导致重复的递归和计算,可以采取多字段联合汇总,实现方式如下
3.1 先创建联合汇总的VO
@Data
class StatisticsVO {
private Integer teacherNum;
private Integer studentNum;
}
3.2 递归联合汇总
//多字段同时逐级累加
StatisticsVO statisticsByOverall(SchoolVO schoolVO) {
List<SchoolVO> SchoolVOList = schoolVO.getSubSchoolVOList();
if (SchoolVOList == null) {
StatisticsVO statisticsVO = new StatisticsVO();
statisticsVO.setStudentNum(schoolVO.getStudentNum() == null ? 0 : schoolVO.getStudentNum());
statisticsVO.setTeacherNum(schoolVO.getTeacherNum() == null ? 0 : schoolVO.getTeacherNum());
return statisticsVO;
}
Integer totalStudentNum = schoolVO.getStudentNum() == null ? 0 : schoolVO.getStudentNum();
Integer totalTeacherNum = schoolVO.getTeacherNum() == null ? 0 : schoolVO.getTeacherNum();
for (SchoolVO SchoolVO1 : SchoolVOList) {
StatisticsVO statisticsVO = statisticsByOverall(SchoolVO1);
totalStudentNum = totalStudentNum + statisticsVO.getStudentNum();
totalTeacherNum = totalTeacherNum + statisticsVO.getTeacherNum();
}
schoolVO.setTeacherNum(totalTeacherNum);
schoolVO.setStudentNum(totalStudentNum);
StatisticsVO statisticsVO = new StatisticsVO();
statisticsVO.setTeacherNum(totalTeacherNum);
statisticsVO.setStudentNum(totalStudentNum);
return statisticsVO;
}
三 测试用例:本文代码实现技术采用springBoot,代码只截取了关键部分
1 构建树形结构,从最父级学校逐级往下set子级学校VO
public void initOrResetTreeInfo() {
SchoolVO v0 = SchoolVO.builder().name("v0").teacherNum(1).studentNum(2).build();
SchoolVO v1 = SchoolVO.builder().name("v1").teacherNum(1).studentNum(2).build();
SchoolVO v2 = SchoolVO.builder().name("v2").teacherNum(1).studentNum(2).build();
List<SchoolVO> SchoolVOList = Arrays.asList(v1, v2);
v0.setSubSchoolVOList(SchoolVOList);
SchoolVO v3 = SchoolVO.builder().name("v3").teacherNum(1).studentNum(2).build();
SchoolVO v4 = SchoolVO.builder().name("v4").teacherNum(1).studentNum(2).build();
SchoolVOList = Arrays.asList(v3, v4);
v1.setSubSchoolVOList(SchoolVOList);
SchoolVO v5 = SchoolVO.builder().name("v5").teacherNum(1).studentNum(2).build();
SchoolVO v6 = SchoolVO.builder().name("v6").teacherNum(1).studentNum(2).build();
SchoolVOList = Arrays.asList(v5, v6);
v2.setSubSchoolVOList(SchoolVOList);
SchoolVO v7 = SchoolVO.builder().name("v7").teacherNum(1).studentNum(2).build();
SchoolVO v8 = SchoolVO.builder().name("v8").teacherNum(1).studentNum(2).build();
SchoolVOList = Arrays.asList(v7, v8);
v3.setSubSchoolVOList(SchoolVOList);
SchoolVO v9 = SchoolVO.builder().name("v9").teacherNum(1).studentNum(2).build();
SchoolVO v10 = SchoolVO.builder().name("v10").teacherNum(1).studentNum(2).build();
SchoolVO v11 = SchoolVO.builder().name("v11").teacherNum(1).studentNum(2).build();
SchoolVO v12 = SchoolVO.builder().name("v12").teacherNum(1).studentNum(2).build();
SchoolVOList = Arrays.asList(v9, v10, v11, v12);
v5.setSubSchoolVOList(SchoolVOList);
SchoolVO v13 = SchoolVO.builder().name("v13").teacherNum(1).studentNum(2).build();
SchoolVO v14 = SchoolVO.builder().name("v14").teacherNum(1).studentNum(2).build();
SchoolVOList = Arrays.asList(v13, v14);
v11.setSubSchoolVOList(SchoolVOList);
System.out.println(v0);
}
2 service 调用各自的汇总方式
//单独字段汇总
@Override
public SchoolVO treeStatisticsBySign(SchoolVO schoolVO) {
statisticslBySign(schoolVO);
return schoolVO;
}
//联合字段汇总
@Override
public SchoolVO tressStatisticsByOverall(SchoolVO schoolVO) {
statisticsByOverall(schoolVO);
return schoolVO;
}
3 初始化的树形结构
四 输出结果(因树形层级比较多,结果只截图一部分):
1 单独汇总的结果(以汇总老师数量为例)
2 联合汇总的结果