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

Java构建Tree并实现节点名称模糊查询

乐于学习分享… 大家加油努力

package com.tom.backtrack;import lombok.Data;
import lombok.Getter;import java.util.ArrayList;
import java.util.List;
import java.util.Objects;/*** 树节点** @author zx* @date 2025-05-27 19:51*/
@Data
public class TreeNode {private Long id;private Long parentId;private String name;private List<TreeNode> children;/*** 是否根节点*/@Getterprivate Boolean rootNode;/*** 是否叶子节点**/@Getterprivate Boolean leafNode;/*** 设置子节点数据,设置为protected禁止外部调用**/public void setChildren(List<TreeNode> children) {this.children = children;this.rootNode = Objects.equals(getParentId(), 0L);this.leafNode = children == null || children.isEmpty();}// 模糊搜索方法,返回符合条件的节点列表public List<TreeNode> fuzzySearch(String query) {List<TreeNode> results = new ArrayList<>(); // 存储搜索结果fuzzySearchHelper(this, query, results); // 调用搜索辅助方法return results;}// 判断节点是否有子节点的方法private boolean hasLeaf(TreeNode node) {for (TreeNode child : node.children) {if (child.children.isEmpty()) { // 如果存在叶子节点,返回truereturn true;}}return false; // 否则返回false}// 判断节点的子节点是否存在符合条件的节点的方法private boolean hasMatchingChild(TreeNode node, String query) {for (TreeNode child : node.children) {if (child.name.contains(query) || hasMatchingChild(child, query)) {return true; // 如果子节点的名称包含查询字符串,或者子节点的子节点存在符合条件的节点,则返回true}}return false; // 否则返回false}// 递归搜索辅助方法private void fuzzySearchHelper(TreeNode node, String query, List<TreeNode> results) {// 如果当前节点的值包含查询字符串,并且至少有一个子节点也符合查询条件,则将其添加到结果列表中if (node.name.contains(query) || hasMatchingChild(node, query)) {results.add(node);}// 递归搜索子节点List<TreeNode> removableChildren = new ArrayList<>();for (TreeNode child : node.children) {fuzzySearchHelper(child, query, results);if (!hasLeaf(child)) {removableChildren.add(child);}}// 删除没有树叶的子节点for (TreeNode child : removableChildren) {node.children.remove(child);}}
}
package com.tom.backtrack;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;/*** <h1>树工具类</h1>* <pre>*  1.该工具类支持: 构建树结构、模糊查询*  2.优化建议:*      1.扁平化处理:如果只需要匹配结果而不需要保持树结构,可以先将所有节点展平为列表再进行过滤*      2.性能优化:*          - 对于大数据量场景,可结合缓存机制或异步加载*          - 使用 equalsIgnoreCase() 支持不区分大小写的模糊匹配*      3.高级模糊匹配:使用正则表达式或第三方库如 Apache Commons Text 的模糊匹配功能*  3.注意事项:*      1.若需返回完整树结构但仅展示匹配路径,可在递归中剪枝保留匹配路径*      2.若数据来源于数据库,推荐在 SQL 层面使用 LIKE '%keyword%' 进行模糊查询以减少内存开销(多次 SQL 查询 + 应用层拼接)**  案例:*  场景假设:*   tree_node 的表,用于存储树形结构数据:*      CREATE TABLE tree_node (*        id BIGINT PRIMARY KEY,*        parent_id BIGINT, -- 父节点ID,顶级节点为0或NULL*        name VARCHAR(255) -- 节点名称*      );*   根据某个关键词模糊查询节点名称,并获取其所有父节点路径或子树结构。*  实现方式一:多次 SQL 查询 + 应用层拼接(推荐)*      步骤:*          - 先模糊查询匹配的节点*          - 递归向上查父节点,直到根节点*          - 应用层构建树结构*      示例代码:*          1.模糊查询匹配节点*              SELECT * FROM tree_node WHERE name LIKE '%keyword%';*          2.根据匹配节点 ID,逐级向上查找父节点*              -- 假设匹配到 id = 5 的节点*              SELECT * FROM tree_node WHERE id = 5;*              SELECT * FROM tree_node WHERE id = (SELECT parent_id FROM tree_node WHERE id = 5);*              -- 依次类推,直到 parent_id 为 NULL 或 0**              通过java、python等代码逻辑循环执行上述语句,构建出完整路径。*  实现方式二:使用存储过程模拟递归查询(适用于固定层级)*      创建一个存储过程,递归查找所有子节点:*          DELIMITER $$**          CREATE PROCEDURE search_tree(IN keyword VARCHAR(255))*          BEGIN*              CREATE TEMPORARY TABLE IF NOT EXISTS temp_result (*                  id BIGINT,*                  parent_id BIGINT,*                  name VARCHAR(255)*              );**              TRUNCATE TABLE temp_result;**              -- 插入初始匹配节点*              INSERT INTO temp_result (id, parent_id, name)*              SELECT id, parent_id, name FROM tree_node WHERE name LIKE CONCAT('%', keyword, '%');**              -- 循环插入父节点*              WHILE ROW_COUNT() > 0 DO*                  INSERT INTO temp_result (id, parent_id, name)*                  SELECT t.id, t.parent_id, t.name*                  FROM tree_node t*                  INNER JOIN temp_result tr ON t.id = tr.parent_id*                  WHERE t.id NOT IN (SELECT id FROM temp_result);*              END WHILE;**              -- 返回结果*              SELECT * FROM temp_result ORDER BY id;**              DROP TEMPORARY TABLE IF EXISTS temp_result;*          END$$**          DELIMITER ;**       调用方式:*          CALL search_tree('1-2-1');*       注意:*          - MySQL 5.7 不支持 CTE,建议优先在应用层处理树结构。*          - 如果可以升级到 MySQL 8.0,可以直接使用递归查询(CTE):*                WITH RECURSIVE cte AS (*                  SELECT * FROM tree_node WHERE name LIKE '%keyword%'*                  UNION ALL*                  SELECT t.* FROM tree_node t INNER JOIN cte c ON t.id = c.parent_id*              )**              SELECT * FROM cte;** </pre>* @author zx* @date 2025-05-27 20:05*/
public class TreeUtil {public static List<TreeNode> buildTree(List<TreeNode> treeNodeList) {if (treeNodeList == null || treeNodeList.size() == 0) {return treeNodeList;}// 2.根据父节点进行分组Map<Long, List<TreeNode>> groups = treeNodeList.stream().collect(Collectors.groupingBy(TreeNode::getParentId));return treeNodeList.stream().filter(Objects::nonNull).peek(pnd -> {List<TreeNode> ts = groups.get(pnd.getId());pnd.setChildren(ts);}).filter(TreeNode::getRootNode).collect(Collectors.toList());}public static List<TreeNode> fuzzySearch(List<TreeNode> treeNodes, String keyword) {List<TreeNode> result = new ArrayList<>();for (TreeNode node : treeNodes) {traverseAndCollect(node, keyword, result);}return result;}private static boolean traverseAndCollect(TreeNode node, String keyword, List<TreeNode> result) {boolean isMatched = false;//模糊查询---这里使用正则表达式,临时使用字符串包含方法if (node.getName().contains(keyword)) {isMatched = true;}if (node.getChildren() != null && !node.getChildren().isEmpty()) {List<TreeNode> matchedChildren = new ArrayList<>();for (TreeNode child : node.getChildren()) {if (traverseAndCollect(child, keyword, result)) {matchedChildren.add(child);isMatched = true;}}// 可选:只保留匹配的子节点node.setChildren(matchedChildren);}if (isMatched) {result.add(node);}return isMatched;}public static List<TreeNode> buildTreeNodeData() {List<TreeNode> treeNodeList = new ArrayList<>();TreeNode treeNode1 = new TreeNode();treeNode1.setId(1L);treeNode1.setParentId(0L);treeNode1.setName("1");treeNodeList.add(treeNode1);TreeNode treeNode2 = new TreeNode();treeNode2.setId(2L);treeNode2.setParentId(0L);treeNode2.setName("2");treeNodeList.add(treeNode2);TreeNode treeNode3 = new TreeNode();treeNode3.setId(3L);treeNode3.setParentId(1L);treeNode3.setName("1-1");treeNodeList.add(treeNode3);TreeNode treeNode4 = new TreeNode();treeNode4.setId(4L);treeNode4.setParentId(1L);treeNode4.setName("1-2");treeNodeList.add(treeNode4);TreeNode treeNode5 = new TreeNode();treeNode5.setId(5L);treeNode5.setParentId(4L);treeNode5.setName("1-2-1");treeNodeList.add(treeNode5);TreeNode treeNode6 = new TreeNode();treeNode6.setId(6L);treeNode6.setParentId(2L);treeNode6.setName("2-1");treeNodeList.add(treeNode6);TreeNode treeNode7 = new TreeNode();treeNode7.setId(7L);treeNode7.setParentId(2L);treeNode7.setName("2-2");treeNodeList.add(treeNode7);TreeNode treeNode8 = new TreeNode();treeNode8.setId(8L);treeNode8.setParentId(6L);treeNode8.setName("2-2-1");treeNodeList.add(treeNode8);return treeNodeList;}public static void main(String[] args) {List<TreeNode> treeNodeList = buildTree(buildTreeNodeData());List<TreeNode> newTreeNodeList = new ArrayList<>();newTreeNodeList.addAll(treeNodeList);System.out.println(newTreeNodeList);String keyword = "1-2-1";List<TreeNode> searchResultTreeNodeList = buildTree(fuzzySearch(treeNodeList, keyword));System.out.println(searchResultTreeNodeList);}
}

相关文章:

Java构建Tree并实现节点名称模糊查询

乐于学习分享… 大家加油努力 package com.tom.backtrack;import lombok.Data; import lombok.Getter;import java.util.ArrayList; import java.util.List; import java.util.Objects;/*** 树节点** author zx* date 2025-05-27 19:51*/ Data public class TreeNode {private …...

shadcn/ui

文章目录 前言✅ 核心特点&#x1f4e6; 支持组件&#xff08;常用&#xff09;&#x1f680; 安装使用&#xff08;框架支持&#xff09;初始化&#xff08;Next.js 项目为例&#xff09;添加一个组件 &#x1f9e0; 对比其他组件库&#x1f4d8; 官方资源✅ 总结✅ 功能特性&…...

华为FreeArc能和其他华为产品共用充电线吗?

最近刚买的FreeArc终于到手啦&#xff0c;看到网上有朋友说&#xff0c;这次的耳机是不附带充电线&#xff0c;开箱后发现果真如此&#xff0c;那FreeArc到底用什么规格的充电线&#xff0c;能不能和华为的Type-C数据线通用&#xff0c;我来给大家解答一下吧&#xff01; Free…...

[网页五子棋][匹配模式]创建房间类、房间管理器、验证匹配功能,匹配模式小结

文章目录 创建房间类创建房间类实现房间管理器 实现匹配器(3)验证匹配功能问题&#xff1a;匹配按钮不改变验证多开 小结 创建房间类 LOL&#xff0c;通过匹配的方式&#xff0c;自动给你加入到一个房间&#xff0c;也可手动创建游戏房间 这一局游戏&#xff0c;进行的“场所…...

实验设计与分析(第6版,Montgomery)第3章单因子实验:方差分析3.11思考题3.7 R语言解题

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅珏生译) 第3章单因子实验&#xff1a;方差分析3.11思考题3.7 R语言解题。主要涉及单因子方差分析&#xff0c;正态性假设检验&#xff0c;残差与拟合值的关系图&#xff0c;平方根变换。 X<-c(…...

【知识点】第2章:Python程序实例解析

文章目录 知识点整理Python程序语法元素分析 练习题判断题填空题选择题 知识点整理 Python程序语法元素分析 Python程序包括格式框架、注释、变量、表达式、分支语句、循环语句、函数等语法元素。 程序的格式框架 Python语言采用严格的 “缩进” 来表明程序的格式框架。缩进…...

从解决一个分享图片生成的历史bug出发,详解LayoutInflater和View.post的工作原理

问题背景 最近在项目中遇到一个问题&#xff1a;在档口分享功能中&#xff0c;需要动态生成一个分享图片。代码是这样写的&#xff1a; // 项目中的代码 val shareView LayoutInflater.from(thisStallMainActivityV1).inflate(R.layout.share_header_stall_main_layout, nul…...

Ubuntu 22.04 上使用 Docker 安装 RagFlow

GitHub地址:添加链接描述 RAGFlow 是一款开源的检索增强生成(Retrieval-Augmented Generation,简称 RAG)引擎,旨在通过深度文档理解技术,结合大语言模型(LLM),为用户提供高质量、可溯源的问答服务。 🚀 快速入门 RAGFlow 提供了便捷的部署方式,支持 Docker 环境。…...

每日Prompt:指尖做画

提示词 微缩景观&#xff0c;微距摄影&#xff0c;俯瞰角度&#xff0c;特写&#xff0c;硕大食指手指甲&#xff0c;一个小小的人正在做画&#xff0c;小人右手拿画笔&#xff0c;小人左手拿调色盘&#xff0c;在指甲上作画&#xff0c;画的是中国古代山水画&#xff0c;背景…...

Python打卡训练营day40——2025.05.30

知识点回顾&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中 展平操作&#xff1a;除第一个维度batchsize外全部展平 dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout 作业&#xff1a;仔细学习下测试和训练…...

Java八股-数据类型转换有哪些?类型互转会有什么问题?为什么用bigDecimal 不用double ?自动装箱和拆箱?包装类?

Java中有哪些数据类型转换&#xff1f; 显示类型转换&#xff1a;在前面一个括号&#xff0c;里面写上要转换的类型 隐式类型转换&#xff1a;小范围的数据类型转大范围的&#xff0c;int到long&#xff0c;float到double 字符串转整形或浮点&#xff1a;整形&#xff1a;In…...

redis未授权(CVE-2022-0543)

概述 Redis 默认绑定在 0.0.0.0:6379&#xff0c;在未配置防火墙或访问控制的情况下会将服务暴露在公网上。若未设置访问密码&#xff08;默认通常为空&#xff09;&#xff0c;攻击者可直接未授权访问 Redis。利用 Redis 提供的 CONFIG 命令&#xff0c;攻击者可修改配置并将…...

【运维实战】Linux 中su和sudo之间的区别以及如何配置sudo!

Linux 系统相比其他操作系统具有更高的安全性&#xff0c;其安全机制的核心之一在于用户管理策略和权限控制--普通用户默认无权执行任何系统级操作。 若普通用户需要进行系统级变更&#xff0c;必须通过su或sudo命令提权。 1.su与sudo的本质区别 su 要求直接共享 root 密码&…...

LevelDB、BoltDB 和 RocksDB区块链应用比较

LevelDB、BoltDB 和 RocksDB 是三种常用的键值存储数据库&#xff0c;它们在区块链领域&#xff08;如以太坊、比特币等&#xff09;或其他高性能应用中有广泛应用。虽然它们都是嵌入式键值存储&#xff0c;但设计目标、性能特性、功能支持和适用场景有显著差异。以下是它们的详…...

c/c++的opencv图像金字塔缩放

图像金字塔缩放&#xff1a;OpenCV C/C 实践 &#x1f4d0; 图像金字塔是计算机视觉中一种重要且基础的多尺度表示方法。它通过对原始图像进行连续的下采样&#xff08;缩小&#xff09;或上采样&#xff08;放大&#xff09;操作&#xff0c;生成一系列不同分辨率的图像。这些…...

PDF文件转换之输出指定页到新的 PDF 文件

背景 一份 PDF 学习资料需要打印其中某几页&#xff0c;文件有几百兆&#xff0c;看到 WPS 有PDF拆分功能&#xff0c;但是需要会员&#xff0c;开了一个月会员后完成了转换。突然想到&#xff0c;会员到期后如果还要拆解的话&#xff0c;怎么办呢&#xff1f;PDF 文件拆解功能…...

浏览器之禁止打开控制台【F12】

前言 在有时我们的日常开发工作中&#xff0c;有些项目要求我们增加禁用控制台的要求&#xff0c;这种虽然很鸡肋&#xff0c;但是它确实存在&#xff0c;并且会让哈哈心里觉得很有成就感。 所以今天他来了。 文章目录 前言无限debugger实现思路&#xff1a;效果如下&#xff1…...

进阶智能体实战九、图文需求分析助手(ChatGpt多模态版)(帮你生成 模块划分+页面+表设计、状态机、工作流、ER模型)

🧠 基于 ChatGPT 多模态大模型的需求文档分析助手 本文将介绍如何利用 OpenAI 的 GPT-4o 多模态能力,构建一个智能的需求文档分析助手,自动提取功能模块、菜单设计、字段设计、状态机、流程图和 ER 模型等关键内容。 一、🔧 环境准备 在开始之前,请确保您已经完成了基础…...

GEARS以及与基础模型结合

理解基因扰动的反应是众多生物医学应用的核心。然而&#xff0c;可能的多基因扰动组合数量呈指数级增长&#xff0c;严重限制了实验探究的范围。在此&#xff0c;图增强基因激活与抑制模拟器&#xff08;GEARS&#xff09;&#xff0c;将深度学习与基因-基因关系知识图谱相结合…...

SFINAE(替换并不是错误)机制详解详解

C—SFINAE机制详解 1. 核心概念 SFINAE&#xff08;替换失败并非错误&#xff09;是C模板元编程的核心机制&#xff0c;它规定了&#xff1a; 在模板参数推导/替换过程中如果某个替换导致无效代码不会引发编译错误而是从候选函数集中静默移除该模板特化 关键特性 template …...

怎么用外网打开内网的网址?如在异地在家连接访问公司局域网办公网站

什么是内网&#xff1a;即本地网络&#xff0c;私有网&#xff0c;内网IP&#xff0c;如学校局域网&#xff0c;家庭内网&#xff0c;公司内部网络等。可以简单理解为同一个路由下的几个电脑网络。 外网概念&#xff1a;即公网&#xff0c;互联网&#xff0c;是相对于内网而言…...

计算机网络 | 1.1 计算机网络概述思维导图

附大纲&#xff1a; 计算机网络的概念 一个通过通信设备与线路把不同计算机系统连接起来&#xff0c;实现资源共享和信息传递的系统 计算机网络的组成 从组成成分上 硬件&#xff1a;主机、通信链路、交换设备、通信处理机软件&#xff1a;网络操作系统、聊天软件等协议&…...

AI对软件工程的影响及未来发展路径分析报告

目录 第一部分&#xff1a;引言 研究背景与意义 报告框架与方法论 第二部分&#xff1a;AI对不同行业软件工程的影响分析 数字化行业 制造业 零售业 工业领域 第三部分&#xff1a;大厂AI软件工程实践案例分析 微软 谷歌 阿里巴巴 华为 第四部分&#xff1a;未来…...

redis缓存与数据库协调读写机制设计

1.读机制&#xff1a; 读机制没有太大的争议点&#xff0c;因为缓存机制的设计&#xff0c;就是为了更快的命中目标数据&#xff0c;所以读机制先天固定好了&#xff1a;先去读取缓存&#xff0c;缓存未命中再去读取数据库。 2.写机制&#xff1a; 写机制其实也没什么争议点…...

最悉心的指导教程——阿里云创建ECS实例教程+Vue+Django前后端的服务器部署(通过宝塔面板)

各位看官老爷们&#xff0c;点击关注不迷路哟。你的点赞、收藏&#xff0c;一键三连&#xff0c;是我持续更新的动力哟&#xff01;&#xff01;&#xff01; 阿里云创建ECS实例教程 注意&#xff1a; 阿里云有300元额度的免费适用期哟 白嫖~~~~ 注册了阿里云账户后&#x…...

【Python】os模块

目录 &#x1f31f; 前言&#x1f3d7;️ 技术背景与价值&#x1fa79; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f9e0; 一、技术原理剖析&#x1f4ca; 核心架构图解&#x1f4a1; 核心作用讲解&#x1f527; 关键技术模块说明⚖️ 技术选…...

Syslog 全面介绍及在 C 语言中的应用

Syslog 概述 Syslog 是一种工业标准的日志记录协议&#xff0c;用于在网络设备之间传递日志消息。它最早由 Eric Allman 在 1980 年代为 BSD Unix 开发&#xff0c;现在已成为系统和网络管理的重要组成部分。Syslog 协议允许设备将事件消息发送到中央服务器&#xff08;称为 sy…...

windows中Redis、MySQL 和 Elasticsearch启动并正确监听指定端口

Redis&#xff1a;在 localhost 上启动&#xff0c;并监听端口 6379 MySQL&#xff1a;在 localhost 上启动&#xff0c;并监听端口 3306 Elasticsearch&#xff1a;在 127.0.0.1 上启动&#xff0c;并监听端口 9300 1. Redis 确保 Redis 在 localhost 上启动并监听端口 6379…...

Paimon远程文件系统连接机制解析

Paimon 在处理与远程文件系统的连接和使用方面&#xff0c;设计了一套灵活的抽象机制。下面将结合源代码分析 Paimon 是如何实现这一点的。 核心思想是定义一个通用的 FileIO 接口&#xff0c;然后为不同的文件系统提供具体的实现。对于常见的 HDFS、S3、OSS 等&#xff0c;Pa…...

学者观察 | Web3.0的技术革新与挑战——北京理工大学教授沈蒙

导语 沈蒙老师认为Web3.0正推动形成新型数据基础设施架构和数据要素流通机制&#xff0c;有望在数字经济时代发挥重要作用&#xff0c;对我国经济发展和社会进步将产生深远影响。AI在推动Web3.0发展方面具有巨大的潜力&#xff0c;但在隐私保护、公平性与安全性等方面也存在“…...