1.BaseTree
package com.aprilz.common.core.util.tree;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
/**
* @author Aprilz
* @date 2023/3/6-8:56
* @description Tree基类
*/
@Data
public class BaseTree implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "id", required = true, example = "32741")
private Long id;
@ApiModelProperty(value = "父id,顶级父id默认为0", required = true)
private Long parentId;
@ApiModelProperty(value = "排序,从小到大")
private Integer sort;
@ApiModelProperty(value = "父ids,顶级父ids默认为0,如果有多层结构则表现为0::1::4", required = true)
private String parentIds;
@ApiModelProperty(value = "排序,创建时间")
private LocalDateTime updateTime;
@ApiModelProperty(value = "子集")
private List<? extends BaseTree> childList;
@ApiModelProperty(value = "是否计算本身")
private boolean addSelf=false;
}
TreeUtil
package com.aprilz.common.core.util.tree;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson2.util.TypeUtils;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 构建树形结构工具类
*
* @author Aprilz
* @date 2023/3/6-9:13
*/
@SuppressWarnings("unused")
public class TreeUtil {
/**
* 查找最内层子叶子节点数据(没有子节点的节点)
* @param treeList(为排序完后的树)
*/
public static List<? extends BaseTree> findMinNodes(List<? extends BaseTree> treeList) {
List<BaseTree> resultList = new ArrayList<>();
if(CollUtil.isNotEmpty(treeList)){
for (BaseTree tree : treeList) {
List<BaseTree> childList = (List<BaseTree>) tree.getChildList();
if(CollUtil.isNotEmpty(childList)){
resultList.addAll(findMinNodes(childList));
//无节点则直接加入
}else{
resultList.add(tree);
}
}
}
return resultList;
}
/**
* 树形层级 往上统计
* 用法 : TreeUtil.treeCalculatePlus(respVOS,"projectNum");
*
* @param treeList 树层级List
* @param fieldNames 可变长属性名
*/
public static void treeCalculatePlus(List<? extends BaseTree> treeList, String... fieldNames) {
if (fieldNames.length == 0) {
throw new IllegalArgumentException("最少需要一个属性名");
}
if (CollUtil.isNotEmpty(treeList)) {
for (BaseTree tree : treeList) {
List<BaseTree> childList = (List<BaseTree>) tree.getChildList();
if (CollUtil.isNotEmpty(childList)) {
List<BaseTree> collect = childList.stream().filter(tmp -> !tmp.isAddSelf()).collect(Collectors.toList());
//存在未计算的子级则继续重复调用,之后再计算自身
if (collect.size() > 0) {
treeCalculatePlus(childList, fieldNames);
}
//无节点则直接计算
for (String fieldName : fieldNames) {
Object fieldValue = Objects.isNull(ReflectUtil.getFieldValue(tree, fieldName)) ? 0 : ReflectUtil.getFieldValue(tree, fieldName);
Integer sum = TypeUtils.toInteger(fieldValue);
for (BaseTree child : childList) {
sum += TypeUtils.toInteger( Objects.isNull(ReflectUtil.getFieldValue(child, fieldName)) ? 0 : ReflectUtil.getFieldValue(child, fieldName));
}
ReflectUtil.setFieldValue(tree, fieldName, sum);
}
}
//计算完成标识
tree.setAddSelf(true);
}
}
}
}
addSelf默认为false,使用addSelf属性来判断是否计算过,没计算过的,递归往下,直至没有子级为参与计算,此时汇总属性值参与汇总到父级。
gihub代码地址
https://github.com/aprilz-code/tiny.git
https://github.com/aprilz-code/cloud.git