You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从分类树中获取指定ID的分类成员并保留完整上层树形结构

问题解决

现有代码问题

你的代码存在两个核心逻辑缺陷:

  • 第一层筛选逻辑仅保留level=1且ID等于目标ID的根节点,当目标节点是多级子节点时,根节点ID不可能匹配目标ID,无法返回上层层级
  • 树构建逻辑会把父节点下所有子节点全部加入,不会过滤掉不包含目标节点的无关分支(比如示例中的carnivores分支不应该出现在结果中)

实现思路

要保留目标节点的完整祖先层级,需要按以下逻辑处理:

  1. 先将平级的分类列表构建为完整的原始分类树
  2. 递归过滤树节点:仅保留当前节点为目标节点,或者子树中包含目标节点的分支,其余无关节点全部丢弃

可运行代码

import java.util.*;
import java.util.stream.Collectors;

// 对外调用方法:输入目标分类ID、平级全部分类列表,返回过滤后的层级树
private List<CategoryDTO> filterCategoryTreeById(String targetId, List<CategoryDTO> allCategories) {
    if (allCategories.isEmpty()) {
        return Collections.emptyList();
    }
    // 1. 构建完整的原始分类树
    List<CategoryDTO> fullTree = buildFullCategoryTree(allCategories);
    // 2. 过滤只保留包含目标ID的分支
    return fullTree.stream()
            .map(node -> doFilter(node, targetId))
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
}

// 构建完整分类树
private List<CategoryDTO> buildFullCategoryTree(List<CategoryDTO> allCategories) {
    // 按父ID分组,加速子节点查询
    Map<String, List<CategoryDTO>> parentChildrenMap = allCategories.stream()
            .filter(item -> item.getParentId() != null)
            .collect(Collectors.groupingBy(CategoryDTO::getParentId));
    // 筛选所有一级根节点,递归填充子节点
    return allCategories.stream()
            .filter(item -> item.getLevel() == 1)
            .peek(root -> fillChildNodes(root, parentChildrenMap))
            .collect(Collectors.toList());
}

// 递归填充子节点
private void fillChildNodes(CategoryDTO parent, Map<String, List<CategoryDTO>> parentChildrenMap) {
    List<CategoryDTO> children = parentChildrenMap.getOrDefault(parent.getId(), Collections.emptyList());
    parent.setChild(new ArrayList<>(children));
    for (CategoryDTO child : children) {
        fillChildNodes(child, parentChildrenMap);
    }
}

// 递归过滤节点
private CategoryDTO doFilter(CategoryDTO currentNode, String targetId) {
    // 当前节点就是目标,直接返回
    if (currentNode.getId().equals(targetId)) {
        return currentNode;
    }
    // 递归过滤所有子节点
    List<CategoryDTO> filteredChildren = currentNode.getChild().stream()
            .map(child -> doFilter(child, targetId))
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
    // 子节点不为空说明当前节点是目标的祖先节点,保留并替换为过滤后的子节点
    if (!filteredChildren.isEmpty()) {
        currentNode.setChild(filteredChildren);
        return currentNode;
    }
    // 无关节点直接丢弃
    return null;
}

补充说明

你的实体类中字段名为title,如果需要JSON序列化后输出字段名为name,可以在title字段上添加@JsonProperty("name")注解即可。

内容的提问来源于stack exchange,提问作者Minh Nguyễn Nguyễn Đức

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 15:18:03