icexmoon-tree

icexmoon-tree

一个轻量级的 Java 工具库,提供树形结构操作功能。

安装

<dependency><groupId>cn.icexmoon</groupId><artifactId>icexmoon-tree</artifactId><version>1.0.0</version>
</dependency>

使用

构建树

假设需要用树构建的数据类型如下:

@Getter
@Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString
public class Department implements Nodeable<Department> {@EqualsAndHashCode.Includeprivate Long id;private String name;private Long parentId;private Department parent;private List<Department> children;public Department(Long id, String name, Long parentId) {this.id = id;this.name = name;this.parentId = parentId;}
}

这里实现 Nodeable 接口并非必须,getter\setter\equals\hashcode 方法的实现也不是必须。

假设用 Department 构建了一些有树层级关系的测试数据:

public static final List<Department> departments = List.of(new Department(1L, "宇宙科技有限公司", null),new Department(2L, "人事部", 1L),new Department(3L, "系统开发部", 1L),new Department(4L, "开发一部", 3L),new Department(5L, "开发二部", 3L),new Department(6L, "OA项目组", 4L));

这里 Department 实例的父子关系由 parentId 属性指定,当然这也不是必须的,树构建时关联关系依赖于用户提供的匿名函数,只要用户将怎么关联父子信息通过匿名函数告诉树即可。

通过构造函数创建树实例:

public static final Tree<Department> tree = new Tree<>(dept -> {Long id = dept.getId();List<Department> children = new ArrayList<>();for (Department department : departments) {if (department.getParentId() != null && department.getParentId().equals(id)) {children.add(department);}}return children;
}, departments::getFirst);

Tree的构造器需要提供两个参数,都是匿名函数:

  • 匿名函数 GetDirectChildren:提供一个要包含在树节点内的值(Value),返回其所有的子值(Child Value)。
  • 匿名函数 GetRoot:返回根节点的值。

销毁树

树的节点信息是保存在内存中的(Tree 对象的 root 字段),因此如果树创建时依赖的数据的父子关系发生变化,比如 department 表中新增了一个子部门或者删除了一个子部门。需要调用 API 销毁内存中的树结构,以便再次访问树时能重新构建树的父子关系。如果不这么做就可能导致一些 BUG。

销毁树:

tree.destroy();

遍历树

遍历树是一个常见操作,本项目支持通过一个匿名函数 Consumer 在遍历树时对节点执行一些操作:

tree.traversal(node -> {List<Node<Department>> allParents = tree.getAllParents(node);List<String> names = allParents.stream().map(n -> n.getValue().getName()).toList();String fullNames = String.join("/", names);System.out.println(fullNames);
});
  • getAllParents方法会返回指定节点的所有父节点,具体可以参考源码。
  • 默认采用深度优先遍历,提供其他 API 可以指定广度遍历或深度遍历。

查找节点

有时候需要根据指定条件查找树上的某个节点,可以:

Node<Department> findNode = tree.findNode(node -> node.getChildren() != null && node.getValue().getId() == 5);
System.out.println(findNode.getValue());

就像示例展示的,findNode方法接收一个 Predicate 类型的匿名函数作为匹配条件。

简单树拷贝

做前后端分离开发的时候,前端获取到的树不希望是类似:

{value: {id: 1,name: "宇宙科技有限公司",parentId: 0,//...},children[{value: {id: 2,name: "人事部",parentId: 1,//...},children:[...]}]
}

当然,直接使用是没有任何问题的,但如果前端一定要使用类似下面的“简单树”(不包含 Value 这一层)结构:

{id: 1,name: "宇宙科技有限公司",parentId: 0,//...children[{id: 2,name: "人事部",parentId: 1,//...children:[...]}]
}

提供一个 API 可以方便获取一个类似的简单树的拷贝:

Department rootDept = TreeUtil.getSimpleTreeCopy(TestData.tree, Department.class, false);
String jsonString = JSON.toJSONString(rootDept);
System.out.println(jsonString);
  • 因为涉及对象拷贝,所以需要提供一个 Class 对象用于反射。
  • 第三个参数可以控制返回的简单树中是否关联父节点(parent字段),一般来说需要 JSON 后返回给前端的话必须是false,否则会导致 JSON 格式化工具循环遍历进而堆栈溢出。
  • 要操作的数据类型必须有 parent 和 children 属性以及对应的 Getter/Setter 方法,这里引入一个 Nodeable 接口进行限制,也就是说只有实现了该接口才能使用上面的 API。

其它操作

其它相关的操作和 API 可以直接查看源码。

反馈&&建议

项目地址为 icexmoon/icexmoon-tree,你可以从这里查看源码或提交建议。

版本更新记录

1.0.0

初始版本。

1.0.1

简化 POM 文件,移除不必要的依赖传递。修改 Readme 文件描述内容。

The End.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/82412.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习在智能水泥基复合材料中的应用与实践

“机器学习在智能水泥基复合材料中的应用与实践” 课程 内容 机器学习基础模型与复合材料研究融合 机器学习在复合材料中的应用概述机器学习用于复合材料研究的流程复合材料数据收集与数据预处理 实例&#xff1a;数据的收集和预处理 复合材料机器学习特征工程与选择 实例&a…

微软 Build 2025:开启 AI 智能体时代的产业革命

在 2025 年 5 月 19 日的微软 Build 开发者大会上&#xff0c;萨提亚・纳德拉以 "我们已进入 AI 智能体时代" 的宣言&#xff0c;正式拉开了人工智能发展的新纪元。这场汇聚了奥特曼、黄仁勋、马斯克三位科技领袖的盛会&#xff0c;不仅发布了 50 余项创新产品&#…

[Java恶补day6] 15. 三数之和

给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示例 1&a…

《黄帝内经》数学建模与形式化表征方式的重构

黄帝内经的数学概括&#xff1a;《黄帝内经》数学建模与形式化表征方式的重构 摘要&#xff1a;《黄帝内经》通过现代数学理论如动力系统、代数拓扑和随机过程&#xff0c;被重构为一个形式化的人体健康模型。该模型包括阴阳动力学的微分几何、五行代数的李群结构、经络拓扑与同…

理论篇五:如何优化Webpack的打包速度

优化 Webpack 打包速度是提升前端开发效率的关键。以下是 10 种核心优化策略,涵盖开发和生产环境,附带具体配置和实测效果对比: 一、缩小文件搜索范围 1. 指定解析路径(Resolve) resolve: {extensions: [.js, .jsx],

[Windows] 游戏常用运行库- Game Runtime Libraries Package(6.2.25.0409)

游戏常用运行库 合集 整合了许多游戏会用到的运行库&#xff0c;支持 Windows XP – Windows 11 系统&#xff0c;并且支持自动检测系统勾选推荐的运行库&#xff0c;方便快捷。 本版特点&#xff1a; By&#xff1a;mefcl 整合常见最新游戏所需运行库 根据系统自动勾选推荐…

JDK8中的 Stream流式编程用法优化(工具类在文章最后)

Java从JDK8起提供了Stream流这个功能&#xff0c;于是项目里出现了大量基于Stream流的写法。随着项目的进行&#xff0c;慢慢的代码中铺天盖地的都是下面的写法&#xff1a; List<User> userList null;if (condition) {userList new ArrayList<>();userList.add(…

uni-app学习笔记十二-vue3中组件传值(对象传值)

一.单对象传值 父组件定义对象的值 <template><view><UserInfo :obj"userinfo"></UserInfo></view> </template><script setup>import {ref} from "vue"const userinfo ref({name:"蛛儿",avatar:&…

UV-python环境管理工具 入门教程

在学习使用 MCP 的时候接触到了 UV 这个环境管理工具&#xff0c;经过对比&#xff0c;发现它在诸多方面比 venv、conda 等工具更为出色&#xff0c;因此整理了这份简单的入门学习笔记&#xff0c;希望能帮助大家快速上手。 介绍 UV 是一款集 Python 版本管理、虚拟环境创建与…

【漫话机器学习系列】277.梯度裁剪(Gradient Clipping)

【深度学习】什么是梯度裁剪&#xff08;Gradient Clipping&#xff09;&#xff1f;一张图彻底搞懂&#xff01; 在训练深度神经网络&#xff0c;尤其是 RNN、LSTM、Transformer 这类深层结构时&#xff0c;你是否遇到过以下情况&#xff1a; 模型 loss 突然变成 NaN&#xf…

零基础弄懂 ngx_http_slice_module分片缓存加速

一、为什么需要 Slice&#xff1f; 在 NGINX 反向代理或 CDN 场景中&#xff0c;大文件&#xff08;视频、软件包、镜像等&#xff09;常因单体体积过大而令缓存命中率低、回源代价高。 ngx_http_slice_module 通过把一次完整响应拆分成 固定大小的字节块&#xff08;Slice&am…

机器人强化学习入门学习笔记(三)

强化学习&#xff08;Reinforcement Learning, RL&#xff09;与监督学习不同——你不需要预先准备训练数据集&#xff0c;而是要设计环境、奖励函数&#xff0c;让智能体通过交互不断探索和学习。 &#x1f3af; 一、强化学习和训练数据的关系 强化学习不依赖固定的数据集。它…

【python实战】二手房房价数据分析与预测

个人主页&#xff1a;大数据蟒行探索者 目录 一、数据分析目标与任务 1.1背景介绍 1.2课程设计目标与任务 1.3研究方法与技术路线 二、数据预处理 2.1数据说明 2.2数据清洗 2.3数据处理 三、数据探索分析 四、数据分析模型 五、方案评估 摘要&#xff1a;随着社会经…

Kotlin IR编译器插件开发指南

在 Kotlin 中开发基于 IR&#xff08;Intermediate Representation&#xff09;的编译器插件&#xff0c;可以深度定制语言功能或实现高级代码转换。以下是分步骤指南&#xff1a; 一、IR 编译器插件基础 IR 是什么&#xff1f; Kotlin 编译器将源码转换为 IR 中间表示&#xf…

如何用 python 代码复现 MATLAB simulink 的 PID

MATLAB在 Simulink 里做以下设置MATLAB 脚本调用示例 python 实现离散 PID 实现&#xff08;并行形式&#xff09; Simulink 中两种 PID 结构&#xff08;并联形式, I-形式&#xff09;下连续/离散时域里积分增益 I 的表示并联&#xff08;Parallel&#xff09; vs 理想&#x…

黑马点评--基于Redis实现共享session登录

集群的session共享问题分析 session共享问题&#xff1a;多台Tomcat无法共享session存储空间&#xff0c;当请求切换到不同Tomcat服务时&#xff0c;原来存储在一台Tomcat服务中的数据&#xff0c;在其他Tomcat中是看不到的&#xff0c;这就导致了导致数据丢失的问题。 虽然系…

SkyWalking启动失败:OpenSearch分片数量达到上限的完美解决方案

🚨 问题现象 SkyWalking OAP服务启动时报错: org.apache.skywalking.oap.server.library.module.ModuleStartException: java.lang.RuntimeException: {"error":{"root_cause":[{"type":"validation_exception", "reason&q…

向量数据库选型实战指南:Milvus架构深度解析与技术对比

导读&#xff1a;随着大语言模型和AI应用的快速普及&#xff0c;传统数据库在处理高维向量数据时面临的性能瓶颈日益凸显。当文档经过嵌入模型处理生成768到1536维的向量后&#xff0c;传统B-Tree索引的检索效率会出现显著下降&#xff0c;而现代应用对毫秒级响应的严苛要求使得…

MySQL#秘籍#一条SQL语句执行时间以及资源分析

背景 一条 SQL 语句的执行完&#xff0c;每个模块耗时&#xff0c;不同资源(CPU/IO/IPC/SWAP)消耗情况我该如何知道呢&#xff1f;别慌俺有 - MySQL profiling 1. SQL语句执行前 - 开启profiling -- profiling (0-关闭 1-开启) -- 或者&#xff1a;show variables like prof…

【数据结构】实现方式、应用场景与优缺点的系统总结

以下是编程中常见的数据结构及其实现方式、应用场景与优缺点的系统总结&#xff1a; 一、线性数据结构 1. 数组 (Array) 定义&#xff1a;连续内存空间存储相同类型元素。实现方式&#xff1a;int[] arr new int[10]; // Javaarr [0] * 10 # Python操作&#xff1a; 访问&…