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

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树形结构 支持模糊查询,返回匹配节点和父节点,其他节点不返回


http://www.kler.cn/a/586726.html

相关文章:

  • Android开源库——RxJava和RxAndroid
  • Training-free neural architecture search: A review
  • docker构建镜像时总会有部分文件没有被更新,解决办法
  • Android Framework 之了解系统启动流程二
  • 011【fate/extra link】【概率论与数理统计】大数定律与中心极限定理 ,数理统计的基本概念,常用的统计三大分布,正态总体的抽样分布定理
  • Python 实现大文件的高并发下载
  • jenkins通过ssh连接远程服务器出错解决方案(Algorithm negotiation fail)
  • MySQL(第四周)
  • 基于“动手学强化学习”的知识点(六):第 19 章 目标导向的强化学习(gym版本 >= 0.26)
  • C++之OOP
  • 蓝桥杯嵌入式赛道复习笔记1(led点亮)
  • 【Python机器学习】2.4. K均值聚类(KMeans Analysis)实战(进阶)
  • SOME/IP:用Python实现协议订阅、Offer、订阅ACK与报文接收
  • 【Unity网络同步框架 - Nakama研究(二)】
  • Spark 中创建 DataFrame 的2种方式对比
  • 【最后203篇系列】015 几种消息队列的思考
  • docker后台运行,便于后期用命令行进入它的终端
  • 【vscode-03】AUTOSAR CP 插件配置
  • DataWhale 速通AI编程开发:(进阶篇)第3章 提示词(Prompts)配置项
  • AI与人的智能,改变一生的思维模型【7】易得性偏差