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

自定义树形结构转换,Hutool的TreeUtil工具

自定义树形结构转换,Hutool的TreeUtil工具

  • 【一】自定义树形结构转换工具
    • 【1】TreeNode接口设计
    • 【2】TreeUtil工具类设计
    • 【3】使用案例:实现TreeNode接口的节点类
    • 【4】使用案例:使用TreeUtil构建树形结构
  • 【二】Hutool TreeUtil工具
    • 【1】引入pom
    • 【2】配置案例
    • 【3】遍历树形结构
    • 【4】获取指定节点下的所有子节点
  • 【三】Hutool TreeUtil使用案例
    • 【1】定义结构
    • 【2】构建Tree
    • 【3】自定义字段名

【一】自定义树形结构转换工具

在实际开发中,树形结构的数据处理是一个常见的需求。例如,组织架构、分类管理、评论回复、树形菜单等,都需要将数据以树形结构展示。本文将深入解析如何使用Java实现一个通用的树形结构转换工具类,包括 TreeUtil 和 TreeNode 接口的设计与实现。

【1】TreeNode接口设计

首先,需要设计一个 TreeNode 接口,用于约束树节点对象必须具备的一些基本功能和属性。具体包括获取节点ID、父节点ID和子节点列表的方法。

public interface TreeNode<T> {T getId(); // 获取节点IDT getParentId(); // 获取父节点IDvoid setChildren(List<TreeNode<T>> children); // 设置子节点列表List<TreeNode<T>> getChildren(); // 获取子节点列表
}

【2】TreeUtil工具类设计

接下来,设计一个 TreeUtil 工具类,用于将平铺的数据列表转换为树形结构。主要包括两个方法:buildTree 和 findRootNodes。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class TreeUtil {/*** 将平铺的数据列表转换为树形结构* @param nodes 所有节点列表* @param rootParentId 根节点的父ID* @param <T> 节点ID类型* @return 树形结构列表*/public static <T> List<TreeNode<T>> buildTree(List<TreeNode<T>> nodes, T rootParentId) {// 创建一个ID到节点的映射Map<T, TreeNode<T>> nodeMap = new HashMap<>();for (TreeNode<T> node : nodes) {nodeMap.put(node.getId(), node);}// 创建一个用于存储根节点的列表List<TreeNode<T>> rootNodes = new ArrayList<>();// 遍历所有节点,将节点挂载到其父节点上for (TreeNode<T> node : nodes) {T parentId = node.getParentId();if (rootParentId.equals(parentId)) {rootNodes.add(node);} else {TreeNode<T> parentNode = nodeMap.get(parentId);if (parentNode != null) {List<TreeNode<T>> children = parentNode.getChildren();if (children == null) {children = new ArrayList<>();parentNode.setChildren(children);}children.add(node);}}}return rootNodes;}/*** 从平铺的数据列表中找到所有根节点* @param nodes 所有节点列表* @param rootParentId 根节点的父ID* @param <T> 节点ID类型* @return 根节点列表*/public static <T> List<TreeNode<T>> findRootNodes(List<TreeNode<T>> nodes, T rootParentId) {List<TreeNode<T>> rootNodes = new ArrayList<>();for (TreeNode<T> node : nodes) {if (rootParentId.equals(node.getParentId())) {rootNodes.add(node);}}return rootNodes;}
}

【3】使用案例:实现TreeNode接口的节点类

为了更好地理解 TreeNode 接口和 TreeUtil 工具类的使用,下面实现一个具体的节点类 CategoryNode。

import java.util.ArrayList;
import java.util.List;public class CategoryNode implements TreeNode<Long> {private Long id;private Long parentId;private String name;private List<TreeNode<Long>> children = new ArrayList<>();public CategoryNode(Long id, Long parentId, String name) {this.id = id;this.parentId = parentId;this.name = name;}@Overridepublic Long getId() {return id;}@Overridepublic Long getParentId() {return parentId;}@Overridepublic void setChildren(List<TreeNode<Long>> children) {this.children = children;}@Overridepublic List<TreeNode<Long>> getChildren() {return children;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "CategoryNode{" +"id=" + id +", parentId=" + parentId +", name='" + name + '\'' +", children=" + children +'}';}
}

【4】使用案例:使用TreeUtil构建树形结构

展示如何使用 TreeUtil 构建树形结构。

import java.util.Arrays;
import java.util.List;public class TreeUtilExample {public static void main(String[] args) {List<TreeNode<Long>> nodes = Arrays.asList(new CategoryNode(1L, 0L, "Root Node"),new CategoryNode(2L, 1L, "Child Node 1"),new CategoryNode(3L, 1L, "Child Node 2"),new CategoryNode(4L, 2L, "Child Node 1.1"),new CategoryNode(5L, 2L, "Child Node 1.2"),new CategoryNode(6L, 3L, "Child Node 2.1"));List<TreeNode<Long>> tree = TreeUtil.buildTree(nodes, 0L);for (TreeNode<Long> node : tree) {System.out.println(node);}}
}

【二】Hutool TreeUtil工具

Hutool是一个Java工具包,提供了TreeUtil类来处理树形结构。文章详细介绍了如何构建、遍历和操作三级树形目录,包括构造节点列表、构建树形结构、遍历树以及获取子节点的方法。对于更复杂的树形结构,可能需要自定义递归算法。

【1】引入pom

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.5.6</version>
</dependency>

【2】配置案例

 // 1.查数据(全部菜单节点)List<Menu> all = new ArrayList<>();// 2.配置,可以不用配置,使用默认   TreeNodeConfig.DEFAULT_CONFIGTreeNodeConfig config = new TreeNodeConfig();//config.setIdKey("id");//默认为id可以不设置//config.setParentIdKey("parentId");//默认为parentId可以不设置//config.setDeep(4);//最大递归深度config.setWeightKey("priority");//排序字段// 3.转树,Tree<>里面泛型为id的类型List<Tree<Long>> build = TreeUtil.build(all, 0L, config, (object, tree) -> {// 也可以使用 tree.setId(object.getId());等一些默认值tree.setId(object.getId()).setParentId(object.getParentId()).setName(object.getName()).putExtra("icon", object.getIcon()).putExtra("url", object.getUrl()).putExtra("priority", object.getPriority()).putExtra("type", object.getType());});

【3】遍历树形结构

遍历树形结构可以使用TreeUtil.bfs(tree)方法,该方法会按照层级顺序遍历整个树形结构,并返回遍历结果列表。例如:

List<TreeNode> bfsResult = TreeUtil.bfs(tree);

【4】获取指定节点下的所有子节点

如果需要获取指定节点下的所有子节点,可以使用TreeUtil.subtree(node)方法,该方法会返回指定节点的子树结构。例如:

TreeNode node = ...; // 指定节点 List<TreeNode> subtree = TreeUtil.subtree(node);

【三】Hutool TreeUtil使用案例

【1】定义结构

我们假设要构建一个菜单,可以实现系统管理和店铺管理
在这里插入图片描述

【2】构建Tree

// 构建node列表
List<TreeNode<String>> nodeList = CollUtil.newArrayList();nodeList.add(new TreeNode<>("1", "0", "系统管理", 5));
nodeList.add(new TreeNode<>("11", "1", "用户管理", 222222));
nodeList.add(new TreeNode<>("111", "11", "用户添加", 0));
nodeList.add(new TreeNode<>("2", "0", "店铺管理", 1));
nodeList.add(new TreeNode<>("21", "2", "商品管理", 44));
nodeList.add(new TreeNode<>("221", "2", "商品管理2", 2));

TreeNode表示一个抽象的节点,也表示数据库中一行数据。 如果有其它数据,可以调用setExtra添加扩展字段。

// 0表示最顶层的id是0
List<Tree<String>> treeList = TreeUtil.build(nodeList, "0");

因为两个Tree是平级的,再没有上层节点,因此为List。

【3】自定义字段名

//配置
TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
// 自定义属性名 都要默认值的
treeNodeConfig.setWeightKey("order");
treeNodeConfig.setIdKey("rid");
// 最大递归深度
treeNodeConfig.setDeep(3);//转换器
List<Tree<String>> treeNodes = TreeUtil.build(nodeList, "0", treeNodeConfig,(treeNode, tree) -> {tree.setId(treeNode.getId());tree.setParentId(treeNode.getParentId());tree.setWeight(treeNode.getWeight());tree.setName(treeNode.getName());// 扩展属性 ...tree.putExtra("extraField", 666);tree.putExtra("other", new Object());});

通过TreeNodeConfig我们可以自定义节点的名称、关系节点id名称,这样就可以和不同的数据库做对应。


http://www.mrgr.cn/news/51649.html

相关文章:

  • 算法之排序
  • 我只是一个不务正业的程序媛
  • 怎么给PPT文件设置文字动画效果,提高美观度
  • 选择排序,插入排序,快速排序的java简单实现
  • 宇宙之外的生命存在性探究
  • 常用分布的数学期望、方差、特征函数
  • Dos下编译环境搭建和C运行程序生成
  • 2024年第九届数维杯大学生数学建模挑战赛赛题和数维杯国际数学建模 LaTeX 模板
  • 谈Sobel算子的数学推导——原来是四个方向的相加
  • Linux驱动 --- AP3216C三合一环境光传感器驱动
  • 邻接矩阵表示法创建无向图
  • C++中的initializer_list类
  • 计算机挑战赛9
  • Gin框架操作指南02:JSON渲染
  • YoloV10改进:Neck层改进|使用ContextAggregation模块改善Neck的输出特征|即插即用
  • HarmonyOS开发(ArkUI简单使用)
  • 基本计算器 II
  • stm32启动时用到的systeminit、__main说明
  • 使用IMX6UL实现UART串口通信
  • 网络编程(21)——通过beast库快速实现http服务器