树节点基类-TreeNode
# 🎯 简介
TreeNode 是 Hutool 树结构模块中的核心节点类,实现了 Node 接口,用于表示树中的单个节点。它是一个泛型类,支持任意类型的 ID,能够灵活适应不同业务场景的需求。
# 📋 核心特性
- ✅ 支持泛型 ID,适应不同业务场景
- ✅ 包含完整的父子关系属性
- ✅ 支持节点权重排序
- ✅ 提供扩展字段 Map,方便自定义属性
- ✅ 支持链式调用,使用更便捷
- ✅ 实现了 equals 和 hashCode 方法,便于集合操作
# 🛠️ 类结构
typedef TreeNode<T>
├── 属性
│ ├── id: T // 节点ID
│ ├── parentId: T // 父节点ID
│ ├── name: CharSequence // 节点名称
│ ├── weight: Comparable<?> // 权重,默认0
│ └── extra: Map<String, Object> // 扩展字段
├── 构造方法
│ ├── TreeNode() // 空构造
│ └── TreeNode(id, parentId, name, weight) // 带参构造
└── 方法
├── getId(): T // 获取ID
├── setId(id): TreeNode<T> // 设置ID(链式)
├── getParentId(): T // 获取父节点ID
├── setParentId(parentId): TreeNode<T> // 设置父节点ID(链式)
├── getName(): CharSequence // 获取名称
├── setName(name): TreeNode<T> // 设置名称(链式)
├── getWeight(): Comparable<?> // 获取权重
├── setWeight(weight): TreeNode<T> // 设置权重(链式)
├── getExtra(): Map<String, Object> // 获取扩展字段
├── setExtra(extra): TreeNode<T> // 设置扩展字段(链式)
├── equals(o): boolean // 比较相等性(基于ID)
└── hashCode(): int // 获取哈希值(基于ID)
# 🚀 快速开始
# 基本使用
// 创建一个TreeNode实例
TreeNode<Long> node = new TreeNode<>(1L, 0L, "根节点", 0);
// 使用链式调用设置属性
TreeNode<Long> childNode = new TreeNode<Long>()
.setId(2L)
.setParentId(1L)
.setName("子节点1")
.setWeight(1);
// 输出节点信息
Console.log("节点ID: {}", node.getId());
Console.log("节点名称: {}", node.getName());
# 使用扩展字段
// 创建节点
TreeNode<Long> node = new TreeNode<>(1L, 0L, "根节点", 0);
// 设置扩展字段
Map<String, Object> extra = new HashMap<>();
extra.put("icon", "folder");
extra.put("disabled", false);
node.setExtra(extra);
// 获取扩展字段
Console.log("节点图标: {}", node.getExtra().get("icon"));
Console.log("节点是否禁用: {}", node.getExtra().get("disabled"));
# 📖 详细方法
# 构造方法
# TreeNode()
功能:创建一个空的TreeNode实例
使用场景:需要后续通过setter方法设置属性时使用
示例:
TreeNode<Long> node = new TreeNode<>(); node.setId(1L).setName("节点");
# TreeNode(id, parentId, name, weight)
功能:创建一个带初始属性的TreeNode实例
参数:
id:节点IDparentId:父节点IDname:节点名称weight:权重,用于排序
使用场景:已知节点属性时直接创建
示例:
TreeNode<Long> node = new TreeNode<>(1L, 0L, "根节点", 0);
# 属性访问方法
# getId()
功能:获取节点ID
返回值:节点ID,类型为泛型T
示例:
Long id = node.getId();
# setId(id)
功能:设置节点ID
参数:
id- 节点ID返回值:当前节点实例,支持链式调用
示例:
node.setId(2L);
# getParentId()
功能:获取父节点ID
返回值:父节点ID,类型为泛型T
示例:
Long parentId = node.getParentId();
# setParentId(parentId)
功能:设置父节点ID
参数:
parentId- 父节点ID返回值:当前节点实例,支持链式调用
示例:
node.setParentId(1L);
# getName()
功能:获取节点名称
返回值:节点名称,类型为CharSequence
示例:
CharSequence name = node.getName();
# setName(name)
功能:设置节点名称
参数:
name- 节点名称返回值:当前节点实例,支持链式调用
示例:
node.setName("新节点名称");
# getWeight()
功能:获取节点权重
返回值:节点权重,类型为Comparable<?>
示例:
Comparable<?> weight = node.getWeight();
# setWeight(weight)
功能:设置节点权重,用于排序
参数:
weight- 节点权重,越小优先级越高返回值:当前节点实例,支持链式调用
示例:
node.setWeight(10);
# getExtra()
功能:获取扩展字段Map
返回值:扩展字段Map,包含自定义属性
示例:
Map<String, Object> extra = node.getExtra();
# setExtra(extra)
功能:设置扩展字段Map
参数:
extra- 扩展字段Map返回值:当前节点实例,支持链式调用
示例:
Map<String, Object> extra = new HashMap<>(); extra.put("key", "value"); node.setExtra(extra);
# 对象方法
# equals(o)
功能:比较两个节点是否相等
参数:
o- 要比较的对象返回值:如果两个节点ID相同则返回true,否则返回false
示例:
TreeNode<Long> node1 = new TreeNode<>(1L, 0L, "节点1", 0); TreeNode<Long> node2 = new TreeNode<>(1L, 0L, "节点2", 0); Console.log(node1.equals(node2)); // 输出: true
# hashCode()
功能:获取节点的哈希值
返回值:基于节点ID生成的哈希值
示例:
int hash = node.hashCode();
# 🎨 使用场景
# 1. 构建简单树结构
// 创建节点列表
List<TreeNode<Long>> nodeList = new ArrayList<>();
nodeList.add(new TreeNode<>(1L, 0L, "根节点", 0));
nodeList.add(new TreeNode<>(2L, 1L, "子节点1", 1));
nodeList.add(new TreeNode<>(3L, 1L, "子节点2", 2));
nodeList.add(new TreeNode<>(4L, 2L, "叶子节点1", 0));
nodeList.add(new TreeNode<>(5L, 2L, "叶子节点2", 0));
// 使用TreeUtil构建树
List<TreeNode<Long>> tree = TreeUtil.build(nodeList, 0L);
// 输出树结构
Console.log("构建的树: {}", tree);
# 2. 带扩展字段的节点
// 创建带扩展字段的节点
TreeNode<Long> node = new TreeNode<>(1L, 0L, "商品分类", 0);
Map<String, Object> extra = new HashMap<>();
extra.put("icon", "🍎");
extra.put("level", 1);
extra.put("enabled", true);
node.setExtra(extra);
// 使用扩展字段
Console.log("分类图标: {}", node.getExtra().get("icon"));
Console.log("分类级别: {}", node.getExtra().get("level"));
Console.log("是否启用: {}", node.getExtra().get("enabled"));
# 3. 链式调用创建节点
// 使用链式调用快速创建节点
TreeNode<Long> node = new TreeNode<Long>()
.setId(1L)
.setParentId(0L)
.setName("链式节点")
.setWeight(5);
// 继续设置扩展字段
Map<String, Object> extra = new HashMap<>();
extra.put("description", "使用链式调用创建的节点");
node.setExtra(extra);
Console.log("节点信息: {}", node);
# 💡 注意事项
- 泛型ID:
TreeNode支持任意类型的ID,使用时需保持一致性 - 权重排序:权重值越小,节点在同级中的优先级越高,默认值为0
- 扩展字段:
extra字段为null时,调用getExtra()会返回null,建议使用前进行空检查 - 链式调用:所有setter方法都返回当前节点实例,支持链式调用
- equals和hashCode:基于ID比较相等性,便于在集合中使用
- 父节点关系:设置
parentId时,需要确保父节点存在,否则构建树时可能出现问题
# 🚀 性能优化
- 使用带参构造方法可以减少setter调用,提高性能
- 扩展字段Map建议在创建时初始化,避免多次修改
- 对于大量节点的场景,建议预先设置好权重,避免动态调整
# 🔍 最佳实践
- 命名规范:节点名称建议使用有意义的字符串,便于后续处理和展示
- 权重设计:根据业务需求合理设计权重规则,确保节点排序符合预期
- 扩展字段:对于常用的扩展属性,可以考虑封装成实体类,提高代码可读性
- ID类型选择:根据业务场景选择合适的ID类型,如Long、String等
- 父节点管理:建议使用统一的根节点ID(如0或"0"),便于树结构的构建和遍历
# 📝 总结
TreeNode 是 Hutool 树结构模块中的基础节点类,提供了完整的树节点功能。它支持泛型ID、权重排序、扩展字段等特性,能够适应各种复杂的业务场景。通过与 TreeUtil 等工具类配合使用,可以快速构建和操作树结构,提高开发效率。
无论是构建简单的菜单树,还是复杂的组织结构树,TreeNode 都能提供可靠的支持。其链式调用设计和灵活的扩展机制,使得树结构的操作变得更加简洁和高效。