From 81cbb0d8a043a9689987a9613f69cb1a40f66e65 Mon Sep 17 00:00:00 2001 From: huangchengxing <841396397@qq.com> Date: Mon, 4 Jul 2022 15:55:07 +0800 Subject: [PATCH] fix code --- .../java/cn/hutool/core/map/ForestMap.java | 46 +++++++++------ .../cn/hutool/core/map/LinkedForestMap.java | 58 ++++++++++++++++++- .../java/cn/hutool/core/map/TreeEntry.java | 16 +++++ .../hutool/core/map/LinkedForestMapTest.java | 14 ++--- 4 files changed, 108 insertions(+), 26 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/map/ForestMap.java b/hutool-core/src/main/java/cn/hutool/core/map/ForestMap.java index 520f06974..111435a3c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/ForestMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/ForestMap.java @@ -53,7 +53,7 @@ public interface ForestMap extends Map> { treeEntryMap.forEach((k, v) -> { if (v.hasParent()) { final TreeEntry parent = v.getDeclaredParent(); - putLinkedNode(parent.getKey(), parent.getValue(), v.getKey(), v.getValue()); + putLinkedNodes(parent.getKey(), parent.getValue(), v.getKey(), v.getValue()); } else { putNode(v.getKey(), v.getValue()); } @@ -99,7 +99,7 @@ public interface ForestMap extends Map> { values.forEach(v -> { final K key = keyGenerator.apply(v); final K parentKey = parentKeyGenerator.apply(v); - linkNode(parentKey, key); + linkNodes(parentKey, key); get(key).setValue(v); }); } @@ -124,42 +124,54 @@ public interface ForestMap extends Map> { *
  • 若{@code parentKey}或{@code childKey}对应的节点存在,则会更新对应节点的值;
  • * * 该操作等同于: - *
    -	 *     TreeEntry  parent = putNode(parentKey, parentValue);
    -	 *     TreeEntry  child = putNode(childKey, childValue);
    -	 *     linkNode(parentKey, childKey);
    -	 * 
    + *
    {@code
    +	 *     putNode(parentKey, parentValue);
    +	 *     putNode(childKey, childValue);
    +	 *     linkNodes(parentKey, childKey);
    +	 * }
    * * @param parentKey 父节点的key * @param parentValue 父节点的value * @param childKey 子节点的key * @param childValue 子节点的值 */ - default void putLinkedNode(K parentKey, V parentValue, K childKey, V childValue) { - linkNode(parentKey, childKey, (parent, child) -> { - parent.setValue(parentValue); - child.setValue(childValue); - }); + default void putLinkedNodes(K parentKey, V parentValue, K childKey, V childValue) { + putNode(parentKey, parentValue); + putNode(childKey, childValue); + linkNodes(parentKey, childKey); } /** - * 为指定的节点建立父子关系,若{@code parentKey}或{@code childKey}对应节点不存在,则会创建一个对应的值为null的空节点
    + * 添加子节点,并为子节点指定父节点: + *
      + *
    • 若{@code parentKey}或{@code childKey}对应的节点不存在,则会根据键值创建一个对应的节点;
    • + *
    • 若{@code parentKey}或{@code childKey}对应的节点存在,则会更新对应节点的值;
    • + *
    + * + * @param parentKey 父节点的key + * @param childKey 子节点的key + * @param childValue 子节点的值 + */ + void putLinkedNodes(K parentKey, K childKey, V childValue); + + /** + * 为集合中的指定的节点建立父子关系 * * @param parentKey 父节点的key * @param childKey 子节点的key */ - default void linkNode(K parentKey, K childKey) { - linkNode(parentKey, childKey, null); + default void linkNodes(K parentKey, K childKey) { + linkNodes(parentKey, childKey, null); } /** - * 为指定的节点建立父子关系,若{@code parentKey}或{@code childKey}对应节点不存在,则会创建一个对应的值为null的空节点 + * 为集合中的指定的节点建立父子关系 * * @param parentKey 父节点的key * @param childKey 子节点的key * @param consumer 对父节点和子节点的操作,允许为null */ - void linkNode(K parentKey, K childKey, BiConsumer, TreeEntry> consumer); + void linkNodes(K parentKey, K childKey, BiConsumer, TreeEntry> consumer); /** * 若{@code parentKey}或{@code childKey}对应节点都存在,则移除指定该父节点与其直接关联的指定子节点间的引用关系 diff --git a/hutool-core/src/main/java/cn/hutool/core/map/LinkedForestMap.java b/hutool-core/src/main/java/cn/hutool/core/map/LinkedForestMap.java index e0d61589d..8e7d7a95e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/LinkedForestMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/LinkedForestMap.java @@ -210,6 +210,48 @@ public class LinkedForestMap implements ForestMap { return null; } + /** + * 同时添加父子节点: + *
      + *
    • 若{@code parentKey}或{@code childKey}对应的节点不存在,则会根据键值创建一个对应的节点;
    • + *
    • 若{@code parentKey}或{@code childKey}对应的节点存在,则会更新对应节点的值;
    • + *
    + * 该操作等同于: + *
    +	 *     TreeEntry  parent = putNode(parentKey, parentValue);
    +	 *     TreeEntry  child = putNode(childKey, childValue);
    +	 *     linkNodes(parentKey, childKey);
    +	 * 
    + * + * @param parentKey 父节点的key + * @param parentValue 父节点的value + * @param childKey 子节点的key + * @param childValue 子节点的值 + */ + @Override + public void putLinkedNodes(K parentKey, V parentValue, K childKey, V childValue) { + linkNodes(parentKey, childKey, (parent, child) -> { + parent.setValue(parentValue); + child.setValue(childValue); + }); + } + + /** + * 添加子节点,并为子节点指定父节点: + *
      + *
    • 若{@code parentKey}或{@code childKey}对应的节点不存在,则会根据键值创建一个对应的节点;
    • + *
    • 若{@code parentKey}或{@code childKey}对应的节点存在,则会更新对应节点的值;
    • + *
    + * + * @param parentKey 父节点的key + * @param childKey 子节点的key + * @param childValue 子节点的值 + */ + @Override + public void putLinkedNodes(K parentKey, K childKey, V childValue) { + linkNodes(parentKey, childKey, (parent, child) -> child.setValue(childValue)); + } + /** * 为指定的节点建立父子关系,若{@code parentKey}或{@code childKey}对应节点不存在,则会创建一个对应的值为null的空节点 * @@ -218,7 +260,7 @@ public class LinkedForestMap implements ForestMap { * @param consumer 对父节点和子节点的操作,允许为null */ @Override - public void linkNode(K parentKey, K childKey, BiConsumer, TreeEntry> consumer) { + public void linkNodes(K parentKey, K childKey, BiConsumer, TreeEntry> consumer) { consumer = ObjectUtil.defaultIfNull(consumer, (parent, child) -> {}); final TreeEntryNode parentNode = nodes.computeIfAbsent(parentKey, t -> new TreeEntryNode<>(null, t)); TreeEntryNode childNode = nodes.get(childKey); @@ -358,6 +400,7 @@ public class LinkedForestMap implements ForestMap { * * @return 当前节点与根节点的距离 */ + @Override public int getWeight() { return weight; } @@ -454,6 +497,17 @@ public class LinkedForestMap implements ForestMap { return traverseParentNodes(false, p -> {}, p -> p.equalsKey(key)); } + /** + * 获取以当前节点作为根节点的树结构,然后遍历所有节点 + * + * @param includeSelf 是否处理当前节点 + * @param nodeConsumer 对节点的处理 + */ + @Override + public void forEachChild(boolean includeSelf, Consumer> nodeConsumer) { + traverseChildNodes(includeSelf, (index, child) -> nodeConsumer.accept(child), null); + } + /** * 指定key与当前节点的key是否相等 * @@ -577,7 +631,7 @@ public class LinkedForestMap implements ForestMap { } /** - * 获取以当前节点作为根节点的树结构,然后获取该树结构中的当前节点的全部子节点 + * 获取以当前节点作为根节点的树结构,然后按广度优先获取该树结构中的当前节点的全部子节点 * * @return 节点 */ diff --git a/hutool-core/src/main/java/cn/hutool/core/map/TreeEntry.java b/hutool-core/src/main/java/cn/hutool/core/map/TreeEntry.java index a79da969d..358723a48 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/TreeEntry.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/TreeEntry.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import java.util.Map; +import java.util.function.Consumer; /** * 允许拥有一个父节点与多个子节点的{@link Map.Entry}实现, @@ -40,6 +41,13 @@ public interface TreeEntry extends Map.Entry { // ===================== 父节点相关方法 ===================== + /** + * 获取以当前节点作为叶子节点的树结构,然后获取当前节点与根节点的距离 + * + * @return 当前节点与根节点的距离 + */ + int getWeight(); + /** * 获取以当前节点作为叶子节点的树结构,然后获取该树结构的根节点 * @@ -81,6 +89,14 @@ public interface TreeEntry extends Map.Entry { return ObjectUtil.isNotNull(getParent(key)); } + /** + * 获取以当前节点作为根节点的树结构,然后遍历所有节点 + * + * @param includeSelf 是否处理当前节点 + * @param nodeConsumer 对节点的处理 + */ + void forEachChild(boolean includeSelf, Consumer> nodeConsumer); + // ===================== 子节点相关方法 ===================== /** diff --git a/hutool-core/src/test/java/cn/hutool/core/map/LinkedForestMapTest.java b/hutool-core/src/test/java/cn/hutool/core/map/LinkedForestMapTest.java index 570ec0264..27af0b13c 100644 --- a/hutool-core/src/test/java/cn/hutool/core/map/LinkedForestMapTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/map/LinkedForestMapTest.java @@ -31,9 +31,9 @@ public class LinkedForestMapTest { @Before public void beforeTest() { // a -> b -> c -> d - treeNodeMap.linkNode("a", "b"); - treeNodeMap.linkNode("b", "c"); - treeNodeMap.linkNode("c", "d"); + treeNodeMap.linkNodes("a", "b"); + treeNodeMap.linkNodes("b", "c"); + treeNodeMap.linkNodes("c", "d"); } @Test @@ -63,7 +63,7 @@ public class LinkedForestMapTest { Assert.assertEquals(CollUtil.newLinkedHashSet("a", "b", "c", "d"), transKey(treeNodeMap.getTreeNodes("d"))); // 循环依赖 - Assert.assertThrows(IllegalArgumentException.class, () -> treeNodeMap.linkNode("d", "a")); + Assert.assertThrows(IllegalArgumentException.class, () -> treeNodeMap.linkNodes("d", "a")); } @Test @@ -93,7 +93,7 @@ public class LinkedForestMapTest { @Test public void testReRegisterAfterRemove() { // a -> b -> c -> d - treeNodeMap.linkNode("b", "c"); + treeNodeMap.linkNodes("b", "c"); testRegisterBeforeRemove(); } @@ -101,8 +101,8 @@ public class LinkedForestMapTest { public void testParallelRegister() { // a -> b -> c --> d // | -> c2 -> d2 - treeNodeMap.linkNode("b", "c2"); - treeNodeMap.linkNode("c2", "d2"); + treeNodeMap.linkNodes("b", "c2"); + treeNodeMap.linkNodes("c2", "d2"); // getDeclaredChildren Assert.assertEquals(CollUtil.newLinkedHashSet("b", "c", "d", "c2", "d2"), transKey(treeNodeMap.getChildNodes("a")));