Hutool Hutool
(opens new window)
🏡首页
📖指南
🎢最佳实践
💖支持
💡javaDoc (opens new window)
⏳更新记录 (opens new window)
  • 🍎gitee (opens new window)
  • 🍏github (opens new window)
(opens new window)
🏡首页
📖指南
🎢最佳实践
💖支持
💡javaDoc (opens new window)
⏳更新记录 (opens new window)
  • 🍎gitee (opens new window)
  • 🍏github (opens new window)
  • 快速入门

  • 核心(hutool-core)

    • AI(Hutool-ai)

    • 注解(annotation)

    • 数组(array)

    • JavaBean(bean)

    • 缓存(cache)

    • 类加载器(classloader)

    • 编码解码(codec)

    • 集合(collection)

    • 比较器(comparator)

    • 压缩(compress)

    • 类型转换(convert)

    • 数据(data)

    • 日期时间(date)

    • 异常(exception)

    • 函数(func)

    • IO流(io)

    • 语言特性(lang)

    • Map(map)

    • 数字数学(math)

    • 网络(net)

    • 对象池(pool)

    • 反射(reflect)

    • 正则(regex)

    • 服务提供(spi)

    • 聚合操作(stream)

    • 字符串文本(text)

    • 并发和线程(thread)

    • 树结构(tree)

      • 简介
      • 树工具类-TreeUtil
      • 节点接口-Node
        • 🎯 简介
        • 📋 核心特性
        • 🛠️ 接口结构
        • 🚀 快速开始
          • 实现Node接口
          • 使用已有实现类
        • 📖 详细方法
          • getId()
          • setId(id)
          • getParentId()
          • setParentId(parentId)
          • getName()
          • setName(name)
          • getWeight()
          • setWeight(weight)
          • compareTo(node)
        • 🎨 使用场景
          • 1. 自定义节点类型
          • 2. 节点排序
          • 3. 树结构构建
        • 💡 注意事项
        • 🚀 性能优化
        • 🔍 最佳实践
        • 📝 总结
      • 节点解析器-NodeParser
      • 默认节点解析器-DefaultNodeParser
      • 树节点配置-TreeNodeConfig
      • Lambda节点配置-LambdaTreeNodeConfig
      • 树节点基类-TreeNode
      • 基于Map的树节点-MapTree
      • Bean树构建工具-BeanTree
      • 树构建器-TreeBuilder
      • 层级迭代器-HierarchyIterator
    • 工具集合(util)

    • XML操作(xml)

  • 定时任务(hutool-cron)

  • 加密(hutool-crypto)

  • 数据库(hutool-db)

  • 扩展(hutool-extra)

  • HTTP(hutool-http)

  • 日志(hutool-log)

  • 配置文件(hutool-setting)

  • JSON(hutool-json)

  • Office办公(hutool-poi)

  • 套接字(hutool-socket)

  • GUI(hutool-swing)

  • 指南
  • 核心(hutool-core)
  • 树结构(tree)
Hutool
2026-01-03
目录

节点接口-Node

# 🎯 简介

Node 是 Hutool 树结构模块中的核心接口,定义了树节点的基本行为和属性。它是所有树节点类的基础,提供了节点 ID、父节点 ID、节点名称、权重等基本属性的访问方法,并实现了 Comparable 接口用于节点排序。

# 📋 核心特性

  • ✅ 泛型设计,支持任意类型的 ID
  • ✅ 定义了节点的基本属性(ID、父ID、名称、权重)
  • ✅ 支持链式调用,使用更便捷
  • ✅ 实现了 Comparable 接口,可直接用于排序
  • ✅ 实现了 Serializable 接口,支持序列化
  • ✅ 提供默认的 compareTo 实现,基于权重排序
  • ✅ 接口设计简洁,易于实现
  • ✅ 是所有树节点类的基础接口

# 🛠️ 接口结构

typedef Node<T>
  ├── 继承自 Comparable<Node<T>>, Serializable
  └── 方法
      ├── getId(): T // 获取节点ID
      ├── setId(id): Node<T> // 设置节点ID(链式)
      ├── getParentId(): T // 获取父节点ID
      ├── setParentId(parentId): Node<T> // 设置父节点ID(链式)
      ├── getName(): CharSequence // 获取节点名称
      ├── setName(name): Node<T> // 设置节点名称(链式)
      ├── getWeight(): Comparable<?> // 获取权重
      ├── setWeight(weight): Node<T> // 设置权重(链式)
      └── compareTo(node): int // 比较两个节点,基于权重排序

# 🚀 快速开始

# 实现Node接口

// 实现Node接口
class MyNode implements Node<String> {
    private String id;
    private String parentId;
    private String name;
    private Integer weight;

    // 构造方法省略

    @Override
    public String getId() {
        return id;
    }

    @Override
    public Node<String> setId(String id) {
        this.id = id;
        return this;
    }

    @Override
    public String getParentId() {
        return parentId;
    }

    @Override
    public Node<String> setParentId(String parentId) {
        this.parentId = parentId;
        return this;
    }

    @Override
    public CharSequence getName() {
        return name;
    }

    @Override
    public Node<String> setName(CharSequence name) {
        this.name = name.toString();
        return this;
    }

    @Override
    public Comparable<?> getWeight() {
        return weight;
    }

    @Override
    public Node<String> setWeight(Comparable<?> weight) {
        this.weight = (Integer) weight;
        return this;
    }
}

// 使用自定义节点
MyNode root = new MyNode();
root.setId("1")
    .setParentId("0")
    .setName("根节点")
    .setWeight(0);

MyNode child = new MyNode();
child.setId("2")
    .setParentId("1")
    .setName("子节点")
    .setWeight(1);

Console.log("根节点: {}", root);
Console.log("子节点: {}", child);

# 使用已有实现类

// 使用TreeNode实现类
TreeNode<Long> node = new TreeNode<>();
node.setId(1L)
    .setParentId(0L)
    .setName("节点1")
    .setWeight(5);

// 使用MapTree实现类
MapTree<String> mapTree = new MapTree<>();
mapTree.setId("1")
    .setParentId("0")
    .setName("Map节点")
    .setWeight(3);

// 比较节点
int compareResult = node.compareTo(mapTree);
Console.log("节点比较结果: {}", compareResult);

# 📖 详细方法

# getId()

  • 功能:获取节点ID

  • 返回值:节点ID,类型为泛型T

  • 示例:

    String id = node.getId();
    

# setId(id)

  • 功能:设置节点ID

  • 参数:id - 节点ID

  • 返回值:当前节点实例,支持链式调用

  • 示例:

    node.setId("1");
    

# getParentId()

  • 功能:获取父节点ID

  • 返回值:父节点ID,类型为泛型T

  • 示例:

    String parentId = node.getParentId();
    

# setParentId(parentId)

  • 功能:设置父节点ID

  • 参数:parentId - 父节点ID

  • 返回值:当前节点实例,支持链式调用

  • 示例:

    node.setParentId("0");
    

# getName()

  • 功能:获取节点名称

  • 返回值:节点名称,类型为CharSequence

  • 示例:

    CharSequence name = node.getName();
    

# setName(name)

  • 功能:设置节点名称

  • 参数:name - 节点名称

  • 返回值:当前节点实例,支持链式调用

  • 示例:

    node.setName("节点名称");
    

# getWeight()

  • 功能:获取节点权重

  • 返回值:节点权重,类型为Comparable<?>

  • 示例:

    Comparable<?> weight = node.getWeight();
    

# setWeight(weight)

  • 功能:设置节点权重

  • 参数:weight - 节点权重,用于排序

  • 返回值:当前节点实例,支持链式调用

  • 示例:

    node.setWeight(5);
    

# compareTo(node)

  • 功能:比较两个节点,基于权重排序

  • 参数:node - 要比较的节点

  • 返回值:比较结果,负数表示当前节点小于参数节点,0表示相等,正数表示当前节点大于参数节点

  • 默认实现:基于权重比较,如果权重相同则比较节点对象

  • 示例:

    int result = node1.compareTo(node2);
    

# 🎨 使用场景

# 1. 自定义节点类型

// 定义部门节点
class DepartmentNode implements Node<Long> {
    private Long id;
    private Long parentId;
    private String name;
    private Integer orderNum;
    private String deptCode;
    private String leader;

    // 构造方法省略

    // 实现Node接口方法
    @Override
    public Long getId() {
        return id;
    }

    @Override
    public Node<Long> setId(Long id) {
        this.id = id;
        return this;
    }

    @Override
    public Long getParentId() {
        return parentId;
    }

    @Override
    public Node<Long> setParentId(Long parentId) {
        this.parentId = parentId;
        return this;
    }

    @Override
    public CharSequence getName() {
        return name;
    }

    @Override
    public Node<Long> setName(CharSequence name) {
        this.name = name.toString();
        return this;
    }

    @Override
    public Comparable<?> getWeight() {
        return orderNum;
    }

    @Override
    public Node<Long> setWeight(Comparable<?> weight) {
        this.orderNum = (Integer) weight;
        return this;
    }

    // 自定义方法
    public String getDeptCode() {
        return deptCode;
    }

    public DepartmentNode setDeptCode(String deptCode) {
        this.deptCode = deptCode;
        return this;
    }

    public String getLeader() {
        return leader;
    }

    public DepartmentNode setLeader(String leader) {
        this.leader = leader;
        return this;
    }
}

// 使用自定义部门节点
DepartmentNode deptNode = new DepartmentNode();
deptNode.setId(1L)
    .setParentId(0L)
    .setName("技术部")
    .setWeight(1)
    .setDeptCode("TECH")
    .setLeader("张经理");

Console.log("部门节点: {}", deptNode);

# 2. 节点排序

// 创建节点列表
List<Node<Long>> nodeList = new ArrayList<>();

// 添加节点
nodeList.add(new TreeNode<Long>().setId(1L).setParentId(0L).setName("节点1").setWeight(3));
nodeList.add(new TreeNode<Long>().setId(2L).setParentId(0L).setName("节点2").setWeight(1));
nodeList.add(new TreeNode<Long>().setId(3L).setParentId(0L).setName("节点3").setWeight(5));
nodeList.add(new TreeNode<Long>().setId(4L).setParentId(0L).setName("节点4").setWeight(2));

// 排序节点
nodeList.sort(Comparator.naturalOrder());

// 输出排序结果
Console.log("排序后的节点列表: {}", nodeList);

# 3. 树结构构建

// 定义产品分类节点
class CategoryNode implements Node<String> {
    private String id;
    private String parentId;
    private String name;
    private Integer sortOrder;
    private List<CategoryNode> children;

    // 构造方法、getter和setter省略

    // 实现Node接口方法
    @Override
    public String getId() {
        return id;
    }

    @Override
    public Node<String> setId(String id) {
        this.id = id;
        return this;
    }

    @Override
    public String getParentId() {
        return parentId;
    }

    @Override
    public Node<String> setParentId(String parentId) {
        this.parentId = parentId;
        return this;
    }

    @Override
    public CharSequence getName() {
        return name;
    }

    @Override
    public Node<String> setName(CharSequence name) {
        this.name = name.toString();
        return this;
    }

    @Override
    public Comparable<?> getWeight() {
        return sortOrder;
    }

    @Override
    public Node<String> setWeight(Comparable<?> weight) {
        this.sortOrder = (Integer) weight;
        return this;
    }
}

// 创建分类节点列表
List<CategoryNode> categoryList = new ArrayList<>();
categoryList.add(new CategoryNode("1", "0", "电子产品", 1, new ArrayList<>()));
categoryList.add(new CategoryNode("2", "1", "手机", 1, new ArrayList<>()));
categoryList.add(new CategoryNode("3", "1", "电脑", 2, new ArrayList<>()));
categoryList.add(new CategoryNode("4", "2", "智能手机", 1, new ArrayList<>()));
categoryList.add(new CategoryNode("5", "2", "功能手机", 2, new ArrayList<>()));

// 构建分类树
List<CategoryNode> categoryTree = buildTree(categoryList, "0");

Console.log("分类树: {}", categoryTree);

// 简单的树构建方法
private List<CategoryNode> buildTree(List<CategoryNode> nodeList, String rootId) {
    List<CategoryNode> tree = new ArrayList<>();
    for (CategoryNode node : nodeList) {
        if (rootId.equals(node.getParentId())) {
            // 递归构建子树
            node.setChildren(buildTree(nodeList, node.getId()));
            tree.add(node);
        }
    }
    // 排序子节点
    tree.sort(Comparator.naturalOrder());
    return tree;
}

# 💡 注意事项

  1. 泛型类型:

    • T 是节点ID的类型,建议使用不可变类型(如Long、String)
    • 确保所有节点的ID类型一致,否则会导致类型转换错误
  2. 权重排序:

    • 默认的 compareTo 方法基于权重比较
    • 权重值越小,节点优先级越高
    • 如果权重为null,比较结果可能不符合预期,建议始终设置权重
  3. 链式调用:

    • 所有setter方法都返回当前节点实例,支持链式调用
    • 链式调用可以提高代码可读性和编写效率
  4. 实现类:

    • Hutool提供了两个主要实现类:TreeNode 和 MapTree
    • TreeNode 是简单的POJO实现
    • MapTree 是基于Map的动态属性实现
  5. 序列化:

    • 实现了 Serializable 接口,支持序列化和反序列化
    • 自定义实现类时,需要确保所有属性都支持序列化
  6. equals和hashCode:

    • 接口本身没有定义 equals 和 hashCode 方法
    • 自定义实现类时,建议根据ID重写这两个方法

# 🚀 性能优化

  • 对于大量节点的场景,建议使用基本类型作为权重,提高比较效率
  • 实现类中应避免在getter方法中进行复杂计算
  • 对于频繁比较的场景,考虑缓存比较结果

# 🔍 最佳实践

  1. 接口设计:

    • 自定义实现类时,建议遵循接口的方法签名
    • 保持setter方法的链式调用特性
  2. 权重设计:

    • 根据业务需求合理设计权重规则
    • 权重值应具有明确的业务含义
    • 建议使用整数类型作为权重,便于比较和排序
  3. ID选择:

    • 选择合适的ID类型(如Long、String、UUID)
    • 确保ID的唯一性和稳定性
  4. 继承关系:

    • 对于复杂的节点类型,考虑继承已有实现类(如TreeNode)
    • 避免直接实现接口,减少重复代码
  5. 排序使用:

    • 利用接口的 Comparable 实现,方便节点排序
    • 结合Stream API使用,提高代码简洁性

# 📝 总结

Node 接口是 Hutool 树结构模块的核心,定义了树节点的基本行为和属性。它的设计简洁明了,易于实现和使用,为树结构的构建和操作提供了基础。

通过实现 Node 接口,可以创建各种类型的树节点,满足不同业务场景的需求。同时,接口提供的默认 compareTo 实现,使得节点可以直接用于排序,简化了树结构的处理。

在实际开发中,建议优先使用 Hutool 提供的实现类(TreeNode 和 MapTree),如果需要自定义节点类型,可以继承这些实现类或直接实现 Node 接口。

Node 接口的设计体现了面向接口编程的思想,使得树结构的实现更加灵活和可扩展。无论是构建简单的菜单树,还是复杂的组织架构树,Node 接口都能提供可靠的支持。

树工具类-TreeUtil
节点解析器-NodeParser

← 树工具类-TreeUtil 节点解析器-NodeParser→

Theme by Vdoing | Copyright © 2025-2026 Hutool | Apache-2.0
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式