大连全瓷种植牙齿制作中心 发表于 2025-3-16 08:06:21

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: springboot树形布局 支持含糊查询,返回匹配节点和父节点,其他节点不返回