TreeUtil实现列表转换树结构

Hutool文档(官方文档, 最后有个人使用方法)

介绍

考虑到菜单等需求的普遍性,有用户提交了一个扩展性极好的树状结构实现。这种树状结构可以根据配置文件灵活的定义节点之间的关系,也能很好的兼容关系数据库中数据。实现

关系型数据库数据  <->  Tree  <->  JSON

树状结构中最大的问题就是关系问题,在数据库中,每条数据通过某个字段关联自己的父节点,每个业务中这个字段的名字都不同,如何解决这个问题呢?

PR的提供者提供了一种解决思路:自定义字段名,节点不再是一个bean,而是一个map,实现灵活的字段名定义。

使用

定义结构

我们假设要构建一个菜单,可以实现系统管理和店铺管理,菜单的样子如下:

系统管理
    |- 用户管理
    |- 添加用户

店铺管理
    |- 商品管理
    |- 添加商品

那这种结构如何保存在数据库中呢?一般是这样的:

idparentIdnameweight
10系统管理5
111用户管理10
1111用户添加11
20店铺管理5
212商品管理10
2212添加添加11

我们看到,每条数据根据parentId相互关联并表示层级关系,parentId在这里也叫外键。

构建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。

自定义字段名

//配置
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名称,这样就可以和不同的数据库做对应。

个人使用方法

@Override
public DataResult getTreeList(AreaNewReqVo vo) {
    List<AreaNew> list = areaNewMapper.getList(vo);
    TreeNodeConfig config = new TreeNodeConfig();
    config.setParentIdKey("pid");
    config.setWeightKey("sort");
    List<Tree<Integer>> build = TreeUtil.build(list, 0, config, (obj, tree) -> {
        tree.putExtra("id", obj.getId());
        tree.putExtra("pid", obj.getPid());
        tree.putExtra("sort", obj.getSort());
        tree.putExtra("level", obj.getLevel());
        tree.putExtra("icon", obj.getAreaName());
        tree.putExtra("pid", obj.getPid());
        tree.putExtra("code",obj.getCode());
    });
    DataResult dataResult =new DataResult();
    dataResult.setDataSingle(build);
    return dataResult;
}

Mapper查出所需列表

new个TreeNodeConfig(节点配置对象),然后配置判断父级id的是哪个字段 列:“pid”

List<Tree<Integer>> build = TreeUtil.build(list, 0, config, (obj, tree) -> {

TreeUtil.build的四个参数 1,mapper查出的list 2、rootId 表示节点的根部也叫起始ID 3、刚才配置的对象 4、匿名方法

​ 匿名方法内被就是把每个节点需要返回的字段列出来 按上面的格式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 我可以提供一个Java转换树形结构工具类的示例:public class TreeNodeConverter { public static TreeNode convert(Object object) { if (object instanceof TreeNode) { return (TreeNode)object; } TreeNode root = new TreeNode(object); if (object instanceof Map) { Map<Object, Object> map = (Map<Object, Object>)object; for (Object key : map.keySet()) { TreeNode child = convert(map.get(key)); root.add(child); } } else if (object instanceof List) { List<Object> list = (List<Object>)object; for (Object item : list) { TreeNode child = convert(item); root.add(child); } } return root; } } ### 回答2: Java中转换树形结构的工具类可以通过递归来实现。以下是一个简单的示例代码: ```java import java.util.ArrayList; import java.util.List; class TreeNode { private int id; private String name; private List<TreeNode> children; public TreeNode(int id, String name) { this.id = id; this.name = name; this.children = new ArrayList<>(); } public void addChild(TreeNode child) { this.children.add(child); } public int getId() { return id; } public String getName() { return name; } public List<TreeNode> getChildren() { return children; } } public class TreeConverter { public static TreeNode convertToTree(List<TreeNode> nodes) { TreeNode root = null; for (TreeNode node : nodes) { if (node.getId() == 0) { root = node; } else { TreeNode parent = findParent(root, node); if (parent != null) { parent.addChild(node); } } } return root; } private static TreeNode findParent(TreeNode root, TreeNode node) { if (root.getId() == node.getId() / 10) { return root; } for (TreeNode child : root.getChildren()) { TreeNode parent = findParent(child, node); if (parent != null) { return parent; } } return null; } public static void main(String[] args) { List<TreeNode> nodes = new ArrayList<>(); nodes.add(new TreeNode(0, "Root")); nodes.add(new TreeNode(10, "Node1")); nodes.add(new TreeNode(11, "Node2")); nodes.add(new TreeNode(110, "Node3")); nodes.add(new TreeNode(111, "Node4")); TreeNode root = convertToTree(nodes); printTree(root, 0); } private static void printTree(TreeNode node, int level) { StringBuilder prefix = new StringBuilder(); for (int i = 0; i < level; i++) { prefix.append("--"); } System.out.println(prefix + node.getName()); for (TreeNode child : node.getChildren()) { printTree(child, level + 1); } } } ``` 以上代码定义了一个`TreeNode`类表示树的节点,节点有id、name和子节点列表。`TreeConverter`类中有一个`convertToTree`方法,它接收一个节点列表,将节点转换成树形结构,最终返回根节点。`findParent`方法用递归方式寻找节点的父节点。`main`方法中创建了一些节点,并调用`convertToTree`方法将它们转换树结构,然后使用`printTree`方法打印出树的结构。 以上是一个简单的树形结构转换工具类示例。在实际使用中,可以根据需求进行适当的修改和扩展。 ### 回答3: Java转换树形结构的工具类可以提供对树形结构的转换和操作功能,主要包括树的创建、遍历、查找、插入、删除等操作。以下是一个简单的示例工具类: ```java import java.util.ArrayList; import java.util.List; class TreeNode { private int value; private List<TreeNode> children; public TreeNode(int value) { this.value = value; children = new ArrayList<>(); } public int getValue() { return value; } public List<TreeNode> getChildren() { return children; } public void addChild(TreeNode child) { children.add(child); } } public class TreeUtil { public static TreeNode createTree(List<Integer> values) { TreeNode root = null; for (int value : values) { if (root == null) { root = new TreeNode(value); } else { insertNode(root, value); } } return root; } private static void insertNode(TreeNode root, int value) { if (root.getValue() >= value) { for (TreeNode child : root.getChildren()) { if (child.getValue() >= value) { insertNode(child, value); return; } } TreeNode newNode = new TreeNode(value); root.addChild(newNode); } else { TreeNode newNode = new TreeNode(value); newNode.addChild(root); root = newNode; } } public static void preOrderTraversal(TreeNode root) { if (root == null) { return; } System.out.println(root.getValue()); for (TreeNode child : root.getChildren()) { preOrderTraversal(child); } } public static void main(String[] args) { List<Integer> values = new ArrayList<>(); values.add(3); values.add(1); values.add(5); values.add(4); values.add(6); TreeNode root = createTree(values); preOrderTraversal(root); } } ``` 此示例中的`TreeNode`类表示树的节点,包含一个值属性和一个子节点列表。`TreeUtil`工具类提供了创建树、插入节点和前序遍历等功能方法。`createTree`方法根据传入的整数列表创建一个树,`preOrderTraversal`方法对树进行前序遍历打印节点值。 在`main`方法中,我们通过传入一个整数列表创建了一个树,并对树进行了前序遍历输出。这是一个简单示例,你可以根据实际需求来扩展工具类的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值