@Data
public class BaseTree<T extends BaseTree<T>> {
    
    private static final long serialVersionUID = 1L;

    @TableId(value = "id",type = IdType.AUTO)
    private Long id;

    private Long parentId;

    @TableField(exist = false)
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private List<T> children = new ArrayList<>();
    
    public BaseTree() {}

    /**
      * 注意:children一定要new ArrayList<>();不然add会报错的
      * 核心思想就是先拿出list中所有的parentId,再拿出所有id,做差集 拿到的就是一级类目 这里对parentCode为空的数据赋了0值, 如果是固定值可以直接filter 0的数据
      * 递归一级类目下的二级类目,再递归二级类目下的三级类目。。。然后把查到的相应子类目加入到父节点中
      */
    public static <T extends BaseTree<T>> List<T> listToTree(List<T> list) {
        list.forEach(item->{
           if(StringUtils.isBlank(item.getParentCode())){
               item.setParentCode("0");
           }
       });
        Set<Long> parentIds = list.stream().map(BaseTree::getParentId).collect(Collectors.toSet());
        Set<Long> ids = list.stream().map(BaseTree::getId).collect(Collectors.toSet());
        parentIds.removeAll(ids);
        // 我这里可以直接用这个
        // Set<String> parentIds = list.stream().filter(item->item.getParentCode().equals("0")).map(Category::getParentCode).collect(Collectors.toSet());
        //递归查找子结点
        return list.stream()
                   .filter(tree -> parentIds.contains(tree.getParentId()))
                   .map(tree -> findChildren(tree, list))
                   .collect(Collectors.toList());
    }

    private static <T extends BaseTree<T>> T findChildren(T tree, List<T> list) {
        list.stream()
            .filter(node -> node.getParentId().equals(tree.getId()))
            .map(node -> findChildren(node, list))
            .forEachOrdered(children -> tree.getChildren().add(children));
        return tree;
    }

   
    
}

也可以直接写在所在类的方法中

    public List<BasMallCatalogDTO> listToTree(List<BasMallCatalogDTO> list) {
        list.forEach(item->{
           if(StringUtils.isBlank(item.getParentCode())){
               item.setParentCode("0");
           }
       });
        Set<Long> parentIds = list.stream().map(BasMallCatalogDTO::getParentId).collect(Collectors.toSet());
        Set<Long> ids = list.stream().map(BasMallCatalogDTO::getId).collect(Collectors.toSet());
        parentIds.removeAll(ids);
        // 我这里可以直接用这个
        // Set<String> parentIds = list.stream().filter(item->item.getParentCode().equals("0")).map(Category::getParentCode).collect(Collectors.toSet());
        //递归查找子结点
        return list.stream()
                .filter(tree -> parentIds.contains(tree.getParentId()))
                .map(tree -> findChildren(tree, list))
                .collect(Collectors.toList());
    }

    private BasMallCatalogDTO findChildren(BasMallCatalogDTO tree, List<BasMallCatalogDTO> list) {
        list.stream()
                .filter(node -> node.getParentId().equals(tree.getId()))
                .map(node -> findChildren(node, list))
                .forEachOrdered(children -> tree.getChildren().add(children));
        return tree;
    }

 2024-8-5 16:59:23 枚举转树举例, 两种方法


import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author chenyc51748
 */
public class CategoryUtil {

    /**
     * 定义枚举类型
     */
    public enum CategoryEnum {
        /**
         * 关联主体分类
         */

        /**
         * 监管机构分类 type:regulatory_agencies
         * 这里一级分类的parentCode为空用main中listToTree 如果固定为0 用listToTreeTemp
         */
        XXX(null, "XXX", "金融监管", null, "regulatory_agencies"),
        YYY(44, "YYY", "国家外汇管理局", "XXX", "regulatory_agencies"),
        ZZZ(45, "ZZZ", "监管", "YYY", "regulatory_agencies"),
        ;
        // 其他分类...


        /**
         * 数据库中分类数值 (不唯一 关联主体、监管机构...之间的是有相同的 父级分类id是null )
         */
        private final Integer id;
        /**
         * 分类编码 唯一值 用来做转树结构
         */
        private final String code;
        /**
         * 分类名称
         */
        private final String name;
        /**
         * 父类编码
         */
        private final String parentCode;
        /**
         * 分类类型
         */
        private final String type;

        CategoryEnum(Integer id, String code, String name, String parentCode, String type) {
            this.id = id;
            this.code = code;
            this.name = name;
            this.parentCode = parentCode;
            this.type = type;
        }

        public Integer getId() {
            return id;
        }

        public String getCode() {
            return code;
        }

        public String getName() {
            return name;
        }

        public String getParentCode() {
            return parentCode;
        }

        public String getType() {
            return type;
        }

    }

    public static class Category {
        private Integer id;
        private String code;
        private String name;
        // 父分类代码,可能为 null
        private String parentCode;
        private String type;
        // 子类集合
        private List<Category> subCategories;

        public Category(Integer id, String code, String name, String parentCode, String type) {
            this.id = id;
            this.code = code;
            this.name = name;
            this.parentCode = parentCode;
            this.type = type;
            this.subCategories = new ArrayList<>();
        }

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getParentCode() {
            return parentCode;
        }

        public void setParentCode(String parentCode) {
            this.parentCode = parentCode;
        }

        public List<Category> getSubCategories() {
            return subCategories;
        }

        public void setSubCategories(List<Category> subCategories) {
            this.subCategories = subCategories;
        }

        public void addSubCategory(Category subCategory) {
            this.subCategories.add(subCategory);
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        @Override
        public String toString() {
            return "Category{" +
                    "id=" + id +
                    ", code='" + code + '\'' +
                    ", name='" + name + '\'' +
                    ", parentCode='" + parentCode + '\'' +
                    ", type='" + type + '\'' +
                    ", subCategories=" + subCategories +
                    '}';
        }
    }

    /**
     * 将枚举列表转换为 Category 列表
     */
    private static List<Category> enumToList() {
        return Arrays.stream(CategoryEnum.values())
                .map(e -> new Category(e.getId(), e.getCode(), e.getName(), e.getParentCode(), e.getType()))
                .collect(Collectors.toList());
    }

    /**
     * 构建分类树并根据类型返回所有一级分类的列表
     */
    public static List<Category> listToTree(String type) {
        List<Category> allCategories = enumToList();
        Map<String, Category> categoryMap = allCategories.stream()
                .filter(category -> (type == null || type.isEmpty()) || category.getType().equals(type))
                .collect(Collectors.toMap(Category::getCode, Function.identity()));

        List<Category> rootCategories = new ArrayList<>();
        for (Category category : categoryMap.values()) {
            if (category.getParentCode() == null || "0".equals(category.getParentCode())) {
                rootCategories.add(category);
            } else {
                Category parent = categoryMap.get(category.getParentCode());
                if (parent != null) {
                    parent.addSubCategory(category);
                }
            }
        }

        // 递归地构建子分类树
        buildSubCategoriesTree(rootCategories, categoryMap);
        return rootCategories;
    }
    // 递归调用
    private static void buildSubCategoriesTree(List<Category> categories, Map<String, Category> categoryMap) {
        for (Category category : categories) {
            List<Category> children = categoryMap.values().stream()
                    .filter(child -> child.getParentCode() != null && child.getParentCode().equals(category.getCode()))
                    .collect(Collectors.toList());
            category.setSubCategories(children);
            if (!children.isEmpty()) {
                buildSubCategoriesTree(children, categoryMap);
            }
        }
    }

    /**
     * 更新 getCategoryByCode 方法以接受 type 参数并进行筛选
     */
    public static List<Category> getCategoryByCode(String code, String type) {
        // 使用 type 参数筛选
        List<Category> allCategories = listToTree(type);
        List<Category> res = Lists.newArrayList();
        Category temp = allCategories.stream()
                .filter(category -> category.getCode().equals(code))
                .findFirst()
                .orElse(null);
        if (ObjectUtil.isNotEmpty(temp)) {
            res.add(temp);
        }
        return res;
    }
    // 主方法,用于验证
    public static void main(String[] args) {
        // 获取所有一级分类及其子分类的树形结构列表
        // 第一种方法
        List<Category> categories = listToTree("XXX");
        List<Category> allCategories = listToTree(null);
        // 根据指定code拿数据
        // List<Category> res = getCategoryByCode(specificCode, type);
        System.out.println(res);

        // 第二种方法
        List<Category> categories1 = enumToList();
        List<Category> collect = listToTreeTemp(categories1);
        System.out.println(collect);
    }
    public static List<Category> listToTreeTemp(List<Category> list) {
        list.forEach(item->{
           if(StringUtils.isBlank(item.getParentCode())){
               item.setParentCode("0");
           }
       });
        Set<String> parentIds = list.stream().map(Category::getParentCode).collect(Collectors.toSet());
        Set<String> ids = list.stream().map(Category::getCode).collect(Collectors.toSet());
        parentIds.removeAll(ids);
        // 我这里可以直接用这个
        // Set<String> parentIds = list.stream().filter(item->item.getParentCode().equals("0")).map(Category::getParentCode).collect(Collectors.toSet());
        //递归查找子结点
        return list.stream()
                .filter(tree -> parentIds.contains(tree.getParentCode()))
                .map(tree -> findChildren(tree, list))
                .collect(Collectors.toList());
    }

    public static  Category findChildren(Category tree, List<Category> list) {
        list.stream()
                .filter(node -> node.getParentCode().equals(tree.getCode()))
                .map(node -> findChildren(node, list))
                .forEachOrdered(children -> tree.getSubCategories().add(children));
        return tree;
    }

}

2025-3-5 13:50:32

需求:只填充指定id的树结构
 

// list为所有部门数据 现在没有树形结构
public List<Dept> listToTree(List<Dept> list, List<Long> targetIds) {
        // 将所有部门按 id 分组
        Map<Long, Dept> deptMap = list.stream()
                .collect(Collectors.toMap(Dept::getId, dept -> dept));

        // 构建子节点缓存
        Map<Long, List<Dept>> childrenCache = new HashMap<>();
        for (Dept dept : list) {
            if (!childrenCache.containsKey(dept.getParentId())) {
                childrenCache.put(dept.getParentId(), new ArrayList<>());
            }
            childrenCache.get(dept.getParentId()).add(dept);
        }

        // 获取所有目标 id 的子节点
        List<Dept> result = new ArrayList<>();
        for (Long id : targetIds) {
            if (deptMap.containsKey(id)) {
                result.add(buildTree(deptMap.get(id), childrenCache));
            }
        }

        return result;
    }

    private Dept buildTree(Dept tree, Map<Long, List<Dept>> childrenCache) {
        // 获取当前节点的子节点
        List<Dept> children = childrenCache.getOrDefault(tree.getId(), new ArrayList<>());
        children.forEach(child -> buildTree(child, childrenCache));
        tree.setChildren(children);
        return tree;
    }

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐