diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyIterator.java b/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyIterator.java index 0d7b41bad..738f27b54 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyIterator.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyIterator.java @@ -43,7 +43,7 @@ public interface HierarchyIterator { * * @param result 结果 * @param hierarchy 当前层级 - * @return 向容器中添加元素的方法 + * @return 下一需要遍历的层级 */ Collection nextHierarchies(R result, H hierarchy); diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyIteratorImpl.java b/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyIteratorImpl.java index 0362e0e9d..078402dad 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyIteratorImpl.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyIteratorImpl.java @@ -50,7 +50,7 @@ public class HierarchyIteratorImpl implements HierarchyIterator { * * @param result 结果 * @param hierarchy 当前层级 - * @return 向容器中添加元素的方法 + * @return 下一需要遍历的层级 */ @Override public Collection nextHierarchies(final R result, final H hierarchy) { diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyUtil.java index 4e3a15561..8472075ad 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/tree/hierarchy/HierarchyUtil.java @@ -35,11 +35,11 @@ import java.util.function.Predicate; * Node root = Tree.build(); * // 从树结构中通过深度优先查找某个节点 * Node target = HierarchyUtil.traverseByDepthFirst( - * root, HierarchyUtil.finder(Node::getChildren, node -> Objects.equals(node.getId(), "target") ? node : null) + * root, HierarchyIteratorUtil.find(Node::getChildren, node -> Objects.equals(node.getId(), "target") ? node : null) * ); * // 从树结构中通过广度优先获取其所有的子节点 * List nodes = HierarchyUtil.traverseByBreadthFirst( - * root, HierarchyUtil.collector(Node::getChildren) + * root, HierarchyIteratorUtil.collect(Node::getChildren) * ); * } * @@ -123,17 +123,15 @@ public class HierarchyUtil { Objects.requireNonNull(hierarchyIterator); // 遍历层级结构 - final Predicate hierarchyFilter = filter.negate(); final LinkedList queue = new LinkedList<>(); final Set accessed = new HashSet<>(); queue.add(hierarchy); while (!queue.isEmpty()) { // 跳过已经访问过或者被过滤的层级结构 final H curr = queue.removeFirst(); - if (accessed.contains(curr) || hierarchyFilter.test(curr)) { + if (!accessed.add(curr) || !filter.test(curr)) { continue; } - accessed.add(curr); // 若迭代器返回true,则结束遍历 if (hierarchyIterator.isBreak(curr)) { diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/tree/hierarchy/HierarchyUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/tree/hierarchy/HierarchyUtilTest.java index 262b11f00..2d2e2c2fa 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/tree/hierarchy/HierarchyUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/tree/hierarchy/HierarchyUtilTest.java @@ -12,13 +12,12 @@ package org.dromara.hutool.core.tree.hierarchy; +import lombok.Data; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; /** * test for {@link HierarchyUtil} @@ -27,63 +26,72 @@ import java.util.stream.Collectors; */ class HierarchyUtilTest { - private Map tree; + @Data + static class Node { + private String parent; + private String value; + private List children; + + public Node(String parent, String value) { + this.parent = parent; + this.value = value; + } + } + + private Node root; @BeforeEach void init() { - tree = new LinkedHashMap<>(); - // 根节点 - tree.put("0", null); + root = new Node(null, "0"); - // 第一层 - tree.put("0-1", "0"); - tree.put("0-2", "0"); - tree.put("0-3", "0"); + // 第二层 + Node first1 = new Node(root.value, "0-1"); + Node first2 = new Node(root.value, "0-2"); + Node first3 = new Node(root.value, "0-3"); + root.setChildren(Arrays.asList(first1, first2, first3)); // 第三层 - tree.put("0-1-1", "0-1"); - tree.put("0-1-2", "0-1"); - tree.put("0-1-3", "0-1"); + Node second11 = new Node(first1.value, "0-1-1"); + Node second12 = new Node(first1.value, "0-1-2"); + Node second13 = new Node(first1.value, "0-1-3"); + first1.setChildren(Arrays.asList(second11, second12, second13)); - tree.put("0-2-1", "0-2"); - tree.put("0-2-2", "0-2"); - tree.put("0-2-3", "0-2"); + Node second21 = new Node(first2.value, "0-2-1"); + Node second22 = new Node(first2.value, "0-2-2"); + Node second23 = new Node(first2.value, "0-2-3"); + first2.setChildren(Arrays.asList(second21, second22, second23)); - tree.put("0-3-1", "0-3"); - tree.put("0-3-2", "0-3"); - tree.put("0-3-3", "0-3"); + Node second31 = new Node(first3.value, "0-3-1"); + Node second32 = new Node(first3.value, "0-3-2"); + Node second33 = new Node(first3.value, "0-3-3"); + first3.setChildren(Arrays.asList(second31, second32, second33)); } @Test void testTraverseByBreadthFirst() { - // 按广度优先遍历所有节点 - final Set nodes = new LinkedHashSet<>(); - HierarchyUtil.traverseByBreadthFirst("0", HierarchyIteratorUtil.scan(t -> { - nodes.add(t); - return tree.entrySet().stream() - .filter(e -> Objects.equals(t, e.getValue())) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); + // // 按广度优先遍历所有节点 + final List nodes = new ArrayList<>(); + HierarchyUtil.traverseByBreadthFirst(root, HierarchyIteratorUtil.scan(t -> { + nodes.add(t.getValue()); + return t.getChildren(); })); Assertions.assertEquals(13, nodes.size()); Assertions.assertEquals( - new LinkedHashSet<>(Arrays.asList("0", "0-1", "0-2", "0-3", "0-1-1", "0-1-2", "0-1-3", "0-2-1", "0-2-2", "0-2-3", "0-3-1", "0-3-2", "0-3-3")), - nodes + Arrays.asList("0", "0-1", "0-2", "0-3", "0-1-1", "0-1-2", "0-1-3", "0-2-1", "0-2-2", "0-2-3", "0-3-1", "0-3-2", "0-3-3"), + nodes ); // 按广度优先寻找 0-2-3 - final String target = HierarchyUtil.traverseByBreadthFirst("0", HierarchyIteratorUtil.find(parentFinder(), - t -> Objects.equals(t, "0-2-3") ? t : null + final String target = HierarchyUtil.traverseByBreadthFirst(root, HierarchyIteratorUtil.find(Node::getChildren, + t -> Objects.equals(t.getValue(), "0-2-3") ? t.getValue() : null )); Assertions.assertEquals("0-2-3", target); // 按广度优先获取 0-2 的所有子节点 - final List children = HierarchyUtil.traverseByBreadthFirst( - "0", HierarchyIteratorUtil.collect(parentFinder(), - t -> Objects.equals(tree.get(t), "0-2") ? t : null - ) - ); + final List children = HierarchyUtil.traverseByBreadthFirst(root, HierarchyIteratorUtil.collect(Node::getChildren, + t -> Objects.equals(t.getParent(), "0-2") ? t.getValue() : null + )); Assertions.assertEquals(3, children.size()); Assertions.assertEquals(new ArrayList<>(Arrays.asList("0-2-1", "0-2-2", "0-2-3")), children); } @@ -92,40 +100,28 @@ class HierarchyUtilTest { void testTraverseByDepthFirst() { // 按深度优先遍历所有节点 final Set nodes = new LinkedHashSet<>(); - HierarchyUtil.traverseByDepthFirst("0", HierarchyIteratorUtil.scan(t -> { - nodes.add(t); - return tree.entrySet().stream() - .filter(e -> Objects.equals(t, e.getValue())) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); + HierarchyUtil.traverseByDepthFirst(root, HierarchyIteratorUtil.scan(t -> { + nodes.add(t.getValue()); + return t.getChildren(); })); Assertions.assertEquals(13, nodes.size()); Assertions.assertEquals( - new LinkedHashSet<>(Arrays.asList("0", "0-1", "0-1-1", "0-1-2", "0-1-3", "0-2", "0-2-1", "0-2-2", "0-2-3", "0-3", "0-3-1", "0-3-2", "0-3-3")), - nodes + new LinkedHashSet<>(Arrays.asList("0", "0-1", "0-1-1", "0-1-2", "0-1-3", "0-2", "0-2-1", "0-2-2", "0-2-3", "0-3", "0-3-1", "0-3-2", "0-3-3")), + nodes ); // 按深度优先寻找 0-2-3 - final String target = HierarchyUtil.traverseByDepthFirst("0", HierarchyIteratorUtil.find(parentFinder(), - t -> Objects.equals(t, "0-2-3") ? t : null + final String target = HierarchyUtil.traverseByDepthFirst(root, HierarchyIteratorUtil.find(Node::getChildren, + t -> Objects.equals(t.getValue(), "0-2-3") ? t.getValue() : null )); Assertions.assertEquals("0-2-3", target); // 按深度优先获取 0-2 的所有子节点 - final List children = HierarchyUtil.traverseByDepthFirst( - "0", HierarchyIteratorUtil.collect(parentFinder(), - t -> Objects.equals(tree.get(t), "0-2") ? t : null - ) - ); + final List children = HierarchyUtil.traverseByDepthFirst(root, HierarchyIteratorUtil.collect(Node::getChildren, + t -> Objects.equals(t.getParent(), "0-2") ? t.getValue() : null + )); Assertions.assertEquals(3, children.size()); Assertions.assertEquals(new ArrayList<>(Arrays.asList("0-2-1", "0-2-2", "0-2-3")), children); } - private Function> parentFinder() { - return t -> tree.entrySet() - .stream() - .filter(e -> Objects.equals(t, e.getValue())) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - } }