当前位置: 首页 > news >正文

springboot树形结构 支持模糊查询,返回匹配节点和父节点,其他节点不返回

package com.me.meterdemo.ds;
import java.util.ArrayList;
import java.util.List;

public class TreeNode {
    private Long id;
    private String name;
    private Long parentId;
    private List<TreeNode> children = new ArrayList<>();

    // 构造方法
    public TreeNode(Long id, String name, Long parentId) {
        this.id = id;
        this.name = name;
        this.parentId = parentId;
    }

    // Getters and Setters
    public Long getId() { return id; }
    public String getName() { return name; }
    public Long getParentId() { return parentId; }
    public List<TreeNode> getChildren() { return children; }

    public void addChild(TreeNode child) {
        // 防止重复添加
        if (children.stream().noneMatch(c -> c.id.equals(child.id))) {
            children.add(child);
        }
    }
}

package com.me.meterdemo.ds;

import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;



@Service
public class TreeMemoryService {
    // 内存数据存储
    private final Map<Long, TreeNode> nodeMap = new HashMap<>();

    // 初始化测试数据
    @PostConstruct
    private void initData() {
        clearAndInitData();
    }

    private void clearAndInitData() {
        nodeMap.clear();
        addNode(1L, "集团总部", null);
        addNode(2L, "华东公司", 1L);
        addNode(3L, "技术部", 2L);
        addNode(4L, "开发组", 3L);
        addNode(5L, "测试组", 3L);
        addNode(6L, "华南公司", 1L);
    }

    private void addNode(Long id, String name, Long parentId) {
        TreeNode node = new TreeNode(id, name, parentId);
        nodeMap.put(id, node);
    }

    /**
     * 执行树结构搜索
     * @param keyword 查询关键词(可为空)
     * @return 符合条件节点及其父节点组成的树结构
     */
    public List<TreeNode> search(String keyword) {
        // 空关键词返回空结果
        if (keyword != null && keyword.trim().isEmpty()) {
            return Collections.emptyList();
        }

        // 获取所有匹配节点
        List<TreeNode> matches = nodeMap.values().stream()
                .filter(node -> matchesKeyword(node, keyword))
                .collect(Collectors.toList());

        // 收集需要展示的节点ID(匹配节点+父链)
        Set<Long> visibleIds = new LinkedHashSet<>();
        matches.forEach(node -> collectParentChain(node, visibleIds));

        // 构建精简树结构
        return buildPrunedTree(visibleIds);
    }

    // 判断节点是否匹配关键词
    private boolean matchesKeyword(TreeNode node, String keyword) {
        return keyword == null ||
                node.getName().contains(keyword);
    }

    // 收集节点及其所有父节点
    private void collectParentChain(TreeNode node, Set<Long> ids) {
        Long currentId = node.getId();
        while (currentId != null) {
            if (!ids.add(currentId)) break; // 防止循环
            TreeNode current = nodeMap.get(currentId);
            currentId = current.getParentId();
        }
    }

    // 构建修剪后的树结构
    private List<TreeNode> buildPrunedTree(Set<Long> visibleIds) {
        // 创建节点副本防止污染原始数据
        Map<Long, TreeNode> visibleNodes = createNodeCopies(visibleIds);

        // 构建层级关系
        List<TreeNode> roots = new ArrayList<>();
        visibleNodes.values().forEach(node -> {
            Long parentId = node.getParentId();
            if (parentId == null) {
                roots.add(node);
            } else {
                TreeNode parent = visibleNodes.get(parentId);
                if (parent != null) {
                    parent.addChild(node);
                }
            }
        });

        return roots;
    }

    // 创建节点副本(清空原有子节点)
    private Map<Long, TreeNode> createNodeCopies(Set<Long> visibleIds) {
        return visibleIds.stream()
                .map(id -> nodeMap.get(id))
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(
                        TreeNode::getId,
                        orig -> new TreeNode(orig.getId(),
                                orig.getName(),
                                orig.getParentId())
                ));
    }

    // 重置测试数据(可选)
    public void resetData() {
        clearAndInitData();
    }
}

package com.me.meterdemo.ds;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class TreeDSController {
    private final TreeMemoryService treeMemoryService;

    public TreeDSController(TreeMemoryService treeService) {
        this.treeMemoryService = treeService;
    }

    @GetMapping("/search")
    public List<TreeNode> searchTree(@RequestParam(required = false) String keyword) {
        return treeMemoryService.search(keyword);
    }
}

springboot树形结构 支持模糊查询,返回匹配节点和父节点,其他节点不返回

相关文章:

  • Python 基础语法详解
  • 掌握这些 UI 交互设计原则,提升产品易用性
  • Linux内核中断管理总
  • 射频前端模块(FEM)的基本原理与架构:从组成到WiFi路由器的应用
  • 向量数据库对比以及Chroma操作
  • 注解+AOP实现权限控制
  • python自动化处理
  • REDIS生产环境配置
  • 怎么有效降低知网AIGC率
  • JVM常用概念之即时常量
  • python web开发flask库安装与使用
  • 【AI论文】世界建模助力规划更优:具身任务规划中的双偏好优化
  • 蓝桥杯 公因数匹配
  • 电子电气架构 --- 车载电子中常见的动态数据链路库(dll)
  • AUTOSAR 网络安全 架构
  • 【结构设计】3D打印创想三维Ender 3 v2
  • python列表基础知识
  • Java Web 大文件上传优化:从困境到高效
  • 聊聊 Redis 的一些有趣的特性(上)
  • 矩阵的转置
  • 农行深圳市分行原副行长王国彪涉嫌严重违纪违法被查
  • “80后”李灿已任重庆市南川区领导,此前获公示拟提名为副区长人选
  • 宜昌全域高质量发展:机制创新与产业重构的双向突围
  • 中国科协发声:屡禁不止的奇葩论文再次敲响学风建设警钟
  • 李在明正式登记参选下届韩国总统
  • 体坛联播|郑钦文收获红土赛季首胜,国际乒联公布财报