TreeUtil.buildSingle指定rootId节点存在时,作为根节点

This commit is contained in:
Looly 2024-10-02 13:10:51 +08:00
parent 09f6123479
commit 1ba62e8539
3 changed files with 126 additions and 27 deletions

View File

@ -23,6 +23,7 @@ import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.tree.parser.NodeParser;
import org.dromara.hutool.core.util.ObjUtil;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -35,7 +36,7 @@ import java.util.Map;
public class TreeBuilder<E> implements Builder<MapTree<E>> {
private static final long serialVersionUID = 1L;
private final MapTree<E> root;
private MapTree<E> root;
private final Map<E, MapTree<E>> idTreeMap;
private boolean isBuild;
@ -69,8 +70,17 @@ public class TreeBuilder<E> implements Builder<MapTree<E>> {
* @param config 配置
*/
public TreeBuilder(final E rootId, final TreeNodeConfig config) {
root = new MapTree<>(config);
root.setId(rootId);
this(new MapTree<E>(config).setId(rootId));
}
/**
* 构造
*
* @param root 根节点
* @since 5.8.33
*/
public TreeBuilder(final MapTree<E> root) {
this.root = root;
this.idTreeMap = new LinkedHashMap<>();
}
@ -149,6 +159,41 @@ public class TreeBuilder<E> implements Builder<MapTree<E>> {
return this;
}
/**
* 增加节点列表增加的节点是不带子节点的
*
* @param list Bean列表
* @param <T> Bean类型
* @param nodeParser 节点转换器用于定义一个Bean如何转换为Tree节点
* @return this
*/
public <T> TreeBuilder<E> append(final Iterable<T> list, final NodeParser<T, E> nodeParser) {
checkBuilt();
final TreeNodeConfig config = this.root.getConfig();
final Iterator<T> iterator = list.iterator();
return append(new Iterator<MapTree<E>>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public MapTree<E> next() {
final MapTree<E> node = new MapTree<>(config);
nodeParser.parse(iterator.next(), node);
if(ObjUtil.equals(node.getId(), root.getId())){
// issue#IAUSHR 如果指定根节点存在直接复用
TreeBuilder.this.root = node;
return null;
}
return node;
}
});
}
/**
* 增加节点列表增加的节点是不带子节点的
*
@ -157,9 +202,8 @@ public class TreeBuilder<E> implements Builder<MapTree<E>> {
*/
public TreeBuilder<E> append(final Iterable<MapTree<E>> trees) {
checkBuilt();
for (final MapTree<E> tree : trees) {
this.idTreeMap.put(tree.getId(), tree);
if (null != trees) {
append(trees.iterator());
}
return this;
}
@ -167,25 +211,22 @@ public class TreeBuilder<E> implements Builder<MapTree<E>> {
/**
* 增加节点列表增加的节点是不带子节点的
*
* @param list Bean列表
* @param <T> Bean类型
* @param nodeParser 节点转换器用于定义一个Bean如何转换为Tree节点
* @param iterator 节点列表
* @return this
*/
public <T> TreeBuilder<E> append(final List<T> list, final NodeParser<T, E> nodeParser) {
public TreeBuilder<E> append(final Iterator<MapTree<E>> iterator) {
checkBuilt();
final TreeNodeConfig config = this.root.getConfig();
final Map<E, MapTree<E>> map = new LinkedHashMap<>(list.size(), 1);
MapTree<E> node;
for (final T t : list) {
node = new MapTree<>(config);
nodeParser.parse(t, node);
map.put(node.getId(), node);
MapTree<E> tree;
while (iterator.hasNext()) {
tree = iterator.next();
if(null != tree){
this.idTreeMap.put(tree.getId(), tree);
}
}
return append(map);
}
return this;
}
/**
* 重置Builder实现复用

View File

@ -41,7 +41,7 @@ public class TreeUtil {
* @return {@link MapTree}
* @since 5.7.2
*/
public static MapTree<Integer> buildSingle(final List<TreeNode<Integer>> list) {
public static MapTree<Integer> buildSingle(final Iterable<TreeNode<Integer>> list) {
return buildSingle(list, 0);
}
@ -51,7 +51,7 @@ public class TreeUtil {
* @param list 源数据集合
* @return List
*/
public static List<MapTree<Integer>> build(final List<TreeNode<Integer>> list) {
public static List<MapTree<Integer>> build(final Iterable<TreeNode<Integer>> list) {
return build(list, 0);
}
@ -65,7 +65,7 @@ public class TreeUtil {
* @return {@link MapTree}
* @since 5.7.2
*/
public static <E> MapTree<E> buildSingle(final List<TreeNode<E>> list, final E parentId) {
public static <E> MapTree<E> buildSingle(final Iterable<TreeNode<E>> list, final E parentId) {
return buildSingle(list, parentId, TreeNodeConfig.DEFAULT_CONFIG, new DefaultNodeParser<>());
}
@ -77,7 +77,7 @@ public class TreeUtil {
* @param parentId 最顶层父id值 一般为 0 之类
* @return List
*/
public static <E> List<MapTree<E>> build(final List<TreeNode<E>> list, final E parentId) {
public static <E> List<MapTree<E>> build(final Iterable<TreeNode<E>> list, final E parentId) {
return build(list, parentId, TreeNodeConfig.DEFAULT_CONFIG, new DefaultNodeParser<>());
}
@ -93,7 +93,7 @@ public class TreeUtil {
* @return {@link MapTree}
* @since 5.7.2
*/
public static <T, E> MapTree<E> buildSingle(final List<T> list, final E parentId, final NodeParser<T, E> nodeParser) {
public static <T, E> MapTree<E> buildSingle(final Iterable<T> list, final E parentId, final NodeParser<T, E> nodeParser) {
return buildSingle(list, parentId, TreeNodeConfig.DEFAULT_CONFIG, nodeParser);
}
@ -107,7 +107,7 @@ public class TreeUtil {
* @param nodeParser 转换器
* @return List
*/
public static <T, E> List<MapTree<E>> build(final List<T> list, final E parentId, final NodeParser<T, E> nodeParser) {
public static <T, E> List<MapTree<E>> build(final Iterable<T> list, final E parentId, final NodeParser<T, E> nodeParser) {
return build(list, parentId, TreeNodeConfig.DEFAULT_CONFIG, nodeParser);
}
@ -122,7 +122,7 @@ public class TreeUtil {
* @param nodeParser 转换器
* @return List
*/
public static <T, E> List<MapTree<E>> build(final List<T> list, final E rootId, final TreeNodeConfig treeNodeConfig, final NodeParser<T, E> nodeParser) {
public static <T, E> List<MapTree<E>> build(final Iterable<T> list, final E rootId, final TreeNodeConfig treeNodeConfig, final NodeParser<T, E> nodeParser) {
return buildSingle(list, rootId, treeNodeConfig, nodeParser).getChildren();
}
@ -139,7 +139,7 @@ public class TreeUtil {
* @return {@link MapTree}
* @since 5.7.2
*/
public static <T, E> MapTree<E> buildSingle(final List<T> list, final E rootId, final TreeNodeConfig treeNodeConfig, final NodeParser<T, E> nodeParser) {
public static <T, E> MapTree<E> buildSingle(final Iterable<T> list, final E rootId, final TreeNodeConfig treeNodeConfig, final NodeParser<T, E> nodeParser) {
return TreeBuilder.of(rootId, treeNodeConfig)
.append(list, nodeParser).build();
}

View File

@ -0,0 +1,58 @@
package org.dromara.hutool.core.tree;
import lombok.Data;
import org.dromara.hutool.core.tree.parser.NodeParser;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class IssueIAUSHRTest {
@Test
void buildSingleTest() {
final List<TestDept> list= new ArrayList<>();
TestDept sysDept = new TestDept();
sysDept.setDeptId(1L);
sysDept.setDeptName("A");
sysDept.setParentId(null);
list.add(sysDept);
sysDept = new TestDept();
sysDept.setDeptId(2L);
sysDept.setDeptName("B");
sysDept.setParentId(1L);
list.add(sysDept);
sysDept = new TestDept();
sysDept.setDeptId(3L);
sysDept.setDeptName("C");
sysDept.setParentId(1L);
list.add(sysDept);
final TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
treeNodeConfig.setIdKey("deptId");
treeNodeConfig.setNameKey("deptName");
treeNodeConfig.setParentIdKey("parentId");
final NodeParser<TestDept,Long> nodeParser= (dept, tree) ->
tree.setId(dept.getDeptId())
.setParentId(dept.getParentId())
.setName(dept.getDeptName());
final MapTree<Long> longTree = TreeUtil.buildSingle(list, 1L, treeNodeConfig, nodeParser);
assertEquals("A", longTree.getName());
assertEquals(2, longTree.getChildren().size());
assertEquals("B", longTree.getChildren().get(0).getName());
assertEquals("C", longTree.getChildren().get(1).getName());
}
@Data
public static class TestDept {
private Long deptId;
private String deptName;
private Long parentId;
}
}