构建树工具类

简介: 在系统设计中,有许多地方都需要用到树型结构,所以建立一个构建树的工具类,封装关于树操作的一些通用方法,方便使用。

1、应用场景

      在系统设计中,有许多地方都需要用到树型结构,最常见的场景就是电商系统中的商品分类,我们需要将数据库中存储的商品分类取出来并转换为树结构,也需要通过类别的id去过滤出该类别及子类别下的商品信息,这种功能要如何实现呢,所以建立一个构建树工具类,封装构建树的通用方法,方便使用。

2、构建树方法

2.1 代码实现

publicstatic<T>List<T>buildTree(List<T>nodes, Function<T, String>key, Function<T, String>parentKey, Function<T, List<T>>getChildren, BiConsumer<T, List<T>>setChildren) {
List<T>tree=newArrayList<>(16);
Map<String, T>idNodeMap=nodes.stream().collect(Collectors.toMap(key, e->e, (a, b) ->a, LinkedHashMap::new));
idNodeMap.forEach((k, v) -> {
StringparentId=parentKey.apply(v);
if (ROOT_NODE.equals(parentId)) {
tree.add(v);
            } else {
Tt=idNodeMap.get(parentId);
if (ObjectUtil.isNotEmpty(t)) {
List<T>children=getChildren.apply(t);
if (CollectionUtil.isEmpty(children)) {
children=newArrayList<>(16);
setChildren.accept(t, children);
                    }
children.add(v);
                } else {
tree.add(v);
                }
            }
        });
returntree;
    }

2.2 代码讲解

      创建静态方法 buildTree(),这里需要传递五个参数,List<T> nodes:节点列表,Function<T, String> key:获取 key 的函数接口,Function<T, String> parentKey: 获取父 key 的函数接口,Funcation<T, List<T>> getChildren: 获取子节点集合的函数接口,BiConsumer<T, List<T>> setChildren: 设置子节点集合的函数接口。

      方法体中首先定义一个 list 集合并设置初始容量为 16,用于存储树型对象,树型对象一般包含三个属性:节点 id、节点名称和子节点集合。接着通过 stream 流的方式将 nodes集合转为 map, key 在这里可以视为类别的 id,T 可以看作是类别实体对象。

      接着遍历这个 map 集合,通过传入的 parentKey 函数接口,然后调用 apply(v)就可以获取对应的 parentId,然后对 parentId 与根节点标识进行比较,如果相同就直接加入集合中,此时视为顶级类别。如果不同的话,从 map 中获取 parentId 对应的值,如果获取为空,直接加入集合中作为顶级类别,如果不为空的话,就需要通过传入的 getChildren 函数接口,获取该节点父类别中的子节点集合,如果该集合为空,说明当前节点为父类别中的第一个子节点,则需要创建一个 children 集合,调用 setChildren 函数将 children 集合设置为父类别的子节点集合,然后将当前节点加入集合中,如果该集合不为空,则直接将当前节点加入到该集合中即可。通过上诉过程的调用,就可以将一个对象集合转化为树型结构.

3、构建过滤树,排除符合exclude的节点

3.1 代码实现

publicstatic<T>voidexcludeTree(List<T>tree, Function<T, List<T>>getChildren, Predicate<T>exclude) {
tree.removeIf(e-> {
List<T>children=getChildren.apply(e);
if (CollectionUtil.isNotEmpty(children)) {
excludeTree(children, getChildren, exclude);
            }
returnexclude.test(e);
        });
    }

3.2 代码讲解

函数的输入参数包括一个树结构列表tree,一个获取子节点的函数getChildren,和一个判断节点是否需要排除的条件exclude。  

函数的作用是遍历树结构,对每个节点进行判断,如果满足排除条件,则将该节点从树中移除。对于每个节点,还会递归调用excludeTree函数,对其子节点进行相同的处理。  

具体步骤如下:  

1. 使用Lambda表达式定义一个匿名函数e,作为tree.removeIf的参数。该函数的作用是对树结构中的每个节点进行判断和处理。  

2. 在函数内部,首先使用getChildren函数获取当前节点的子节点列表children。  

3. 如果children不为空,则递归调用excludeTree函数,对children进行相同的处理。  

4. 最后,使用exclude函数对当前节点进行判断。如果满足排除条件,则返回true,表示需要将该节点从树中移除;否则返回false,表示保留该节点。

4、根据树以及节点id获取该节点及以下的节点id

4.1 代码实现

publicstatic<T>List<String>getTreeIds(List<T>tree, StringnodeId, Function<T, String>key,  Function<T, List<T>>getChildren) {
if (ObjectUtils.isEmpty(tree) ||StringUtils.isBlank(nodeId)) {
returnnewArrayList<>();
        }
List<String>nodeIds=newArrayList<>();
returngetTreeIds(tree, nodeId, nodeIds, key, getChildren);
    }
publicstatic<T>List<String>getTreeIds(List<T>tree, StringnodeId, List<String>nodeIds, Function<T, String>key, Function<T, List<T>>getChildren) {
if (CollectionUtil.isNotEmpty(tree)) {
tree.forEach(o-> {
if (StringUtils.equals(key.apply(o), nodeId)) {
nodeIds.add(key.apply(o));
getTreeIds(getChildren.apply(o), nodeIds, key, getChildren);
                }
getTreeIds(getChildren.apply(o), nodeId, nodeIds, key, getChildren);
            });
        }
returnnodeIds;
    }
publicstatic<T>voidgetTreeIds(List<T>tree, List<String>nodeIds, Function<T, String>key, Function<T, List<T>>getChildren) {
if(ObjectUtils.isNotEmpty(tree)){
tree.forEach(o-> {
nodeIds.add(key.apply(o));
if (ObjectUtils.isNotEmpty(getChildren.apply(o))) {
getTreeIds(getChildren.apply(o), nodeIds, key, getChildren);
                }
            });
        }
    }

4.2 代码讲解

这段代码用于获取树形结构数据中指定节点及其子节点的id列表。它通过递归遍历树形结构,找到目标节点并将其id添加到列表中,然后继续遍历目标节点的子节点,重复上述操作,直到遍历完所有节点。最终返回包含目标节点及其子节点id的列表。

相关文章
|
5月前
|
算法 Java 测试技术
数据结构 —— Java自定义代码实现顺序表,包含测试用例以及ArrayList的使用以及相关算法题
文章详细介绍了如何用Java自定义实现一个顺序表类,包括插入、删除、获取数据元素、求数据个数等功能,并对顺序表进行了测试,最后还提及了Java中自带的顺序表实现类ArrayList。
75 0
|
9月前
|
Java
Java树状结构数据构建(基于hutool)
Java树状结构数据构建(基于hutool)
187 2
|
9月前
|
算法 前端开发 Java
探讨Java中递归构建树形结构的算法
探讨Java中递归构建树形结构的算法
131 1
|
计算机视觉
轻松编写高效工具类:构建树形结构的秘籍
轻松编写高效工具类:构建树形结构的秘籍
432 0
|
9月前
|
Java
JAVA构建List集合为树形结构的方法和代码
JAVA构建List集合为树形结构的方法和代码
42 0
|
9月前
|
Java
JavaSE——集合框架二(6/6)-(案例)补充知识:集合的嵌套(需求与分析、问题解决、运行测试)
JavaSE——集合框架二(6/6)-(案例)补充知识:集合的嵌套(需求与分析、问题解决、运行测试)
85 0
|
10月前
|
存储 人工智能 Java
Java 构建树型结构
Java 构建树型结构
|
10月前
|
JSON 前端开发 Java
|
10月前
|
Java
java实现遍历树形菜单方法——Dao层
java实现遍历树形菜单方法——Dao层
|
10月前
|
Oracle Java 关系型数据库
java实现遍历树形菜单方法——数据库表的创建
java实现遍历树形菜单方法——数据库表的创建