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

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.xdnf.cn/news/8792.html

相关文章:

  • C语言中的寄存器:理解与应用
  • c/c++的opencv椒盐噪声
  • 【python实战】二手房房价数据分析与预测
  • 日期组合统计
  • 基于MATLAB编程针对NCV检测数据去漂移任务的完整解决方案
  • Java中关于数组的使用(下)
  • NXP应用随记(九):M7内核的Hardfault相关认知
  • PTA刷题笔记(纠细节 有详解)
  • 力扣 74.搜索二维矩阵
  • Vue.extend
  • 工业自动化通信完全指南:西门子/三菱PLC对接
  • 【数据集】30 m地表温度LST数据集
  • OpenHarmony外设驱动使用 (十五),USB
  • 【C++】unordered_map、unordered_set 的使用
  • Java EE 初阶——文件操作和IO
  • NX二次开发-Block UI篇
  • git checkout 通配符
  • C++ queue对象创建、queue赋值操作、queue入队、出队、获得队首、获得队尾操作、queue大小操作、代码练习
  • 【Bluedroid】蓝牙Hid Host get_protocol全流程源码解析
  • docker问题记录
  • 台系厂商SSD主控之争:Phison对决SMI
  • uni-app学习笔记十三-vue3中slot插槽的使用
  • 2025年开发者生存白皮书
  • 中断和信号详解
  • 前端课设Web2
  • MySQL中简单的操作
  • day36 python神经网络训练
  • AI助力,制作视频裁剪软件
  • 达梦数据库-学习-23-获取执行计划的N种方法
  • UE C++学习笔记之创建组件