From 96db994c8751d6fd4550ad7844da24dce13e5b4c Mon Sep 17 00:00:00 2001 From: Earlman Date: Thu, 1 Aug 2024 15:20:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0LambdaTreeNodeConfig=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=EF=BC=8C=E4=BD=BF=E7=94=A8Lambda=E8=AF=AD=E6=B3=95?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E6=A0=91=E8=8A=82=E7=82=B9=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=E8=87=AA=E5=AE=9A=E4=B9=89=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E4=BB=A3=E7=A0=81=E4=B8=AD=E5=AF=B9=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=E7=A1=AC=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/tree/LambdaTreeNodeConfig.java | 110 +++++++++++++++ .../dromara/hutool/core/tree/TreeTest.java | 127 ++++++++++++++---- 2 files changed, 213 insertions(+), 24 deletions(-) create mode 100644 hutool-core/src/main/java/org/dromara/hutool/core/tree/LambdaTreeNodeConfig.java diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/tree/LambdaTreeNodeConfig.java b/hutool-core/src/main/java/org/dromara/hutool/core/tree/LambdaTreeNodeConfig.java new file mode 100644 index 000000000..b40086e6c --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/tree/LambdaTreeNodeConfig.java @@ -0,0 +1,110 @@ +package org.dromara.hutool.core.tree; + +import org.dromara.hutool.core.func.LambdaUtil; +import org.dromara.hutool.core.func.SerFunction; + +import java.util.List; +import java.util.Objects; + +/** + * 树配置属性相关(使用Lambda语法) + * 避免对字段名称硬编码 + * + * @author Earlman + */ +public class LambdaTreeNodeConfig extends TreeNodeConfig { + private SerFunction idKeyFun; + + private SerFunction parentIdKeyFun; + + private SerFunction> weightKeyFun; + + private SerFunction nameKeyFun; + + private SerFunction> childrenKeyFun; + + public SerFunction getIdKeyFun() { + return idKeyFun; + } + + public void setIdKeyFun(SerFunction idKeyFun) { + this.idKeyFun = idKeyFun; + } + + public SerFunction getParentIdKeyFun() { + return parentIdKeyFun; + } + + public void setParentIdKeyFun(SerFunction parentIdKeyFun) { + this.parentIdKeyFun = parentIdKeyFun; + } + + public SerFunction> getWeightKeyFun() { + return weightKeyFun; + } + + public void setWeightKeyFun(SerFunction> weightKeyFun) { + this.weightKeyFun = weightKeyFun; + } + + public SerFunction getNameKeyFun() { + return nameKeyFun; + } + + public void setNameKeyFun(SerFunction nameKeyFun) { + this.nameKeyFun = nameKeyFun; + } + + public SerFunction> getChildrenKeyFun() { + return childrenKeyFun; + } + + public void setChildrenKeyFun(SerFunction> childrenKeyFun) { + this.childrenKeyFun = childrenKeyFun; + } + + @Override + public String getIdKey() { + SerFunction serFunction = getIdKeyFun(); + if (Objects.isNull(serFunction)) { + return super.getIdKey(); + } + return LambdaUtil.getFieldName(serFunction); + } + + @Override + public String getParentIdKey() { + SerFunction serFunction = getParentIdKeyFun(); + if (Objects.isNull(serFunction)) { + return super.getParentIdKey(); + } + return LambdaUtil.getFieldName(serFunction); + } + + @Override + public String getWeightKey() { + SerFunction serFunction = getWeightKeyFun(); + if (Objects.isNull(serFunction)) { + return super.getWeightKey(); + } + return LambdaUtil.getFieldName(serFunction); + } + + @Override + public String getNameKey() { + SerFunction serFunction = getNameKeyFun(); + if (Objects.isNull(serFunction)) { + return super.getNameKey(); + } + return LambdaUtil.getFieldName(serFunction); + } + + @Override + public String getChildrenKey() { + SerFunction serFunction = getChildrenKeyFun(); + if (Objects.isNull(serFunction)) { + return super.getChildrenKey(); + } + return LambdaUtil.getFieldName(serFunction); + } +} diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/tree/TreeTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/tree/TreeTest.java index 760d691f9..4164707f5 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/tree/TreeTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/tree/TreeTest.java @@ -14,6 +14,7 @@ package org.dromara.hutool.core.tree; import org.dromara.hutool.core.collection.ListUtil; import org.dromara.hutool.core.lang.Console; +import org.dromara.hutool.core.tree.parser.DefaultNodeParser; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -59,88 +60,166 @@ public class TreeTest { @Test public void treeTest() { - //配置 + // 配置 final TreeNodeConfig treeNodeConfig = new TreeNodeConfig(); // 自定义属性名 都要默认值的 treeNodeConfig.setWeightKey("order"); treeNodeConfig.setIdKey("rid"); treeNodeConfig.setDeep(2); - //转换器 + // 转换器 final List> 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()); - }); + (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()); + }); Assertions.assertEquals(treeNodes.size(), 2); } @Test - public void walkTest(){ + public void walkTest() { final List ids = new ArrayList<>(); final MapTree tree = TreeUtil.buildSingle(nodeList, "0"); - tree.walk((tr)-> ids.add(tr.getId())); + tree.walk((tr) -> ids.add(tr.getId())); Assertions.assertEquals(7, ids.size()); } @Test - public void walkBroadFirstTest(){ + public void walkBroadFirstTest() { final List ids = new ArrayList<>(); final MapTree tree = TreeUtil.buildSingle(nodeList, "0"); Console.log(tree); - tree.walk((tr)-> ids.add(tr.getId()), true); + tree.walk((tr) -> ids.add(tr.getId()), true); Assertions.assertEquals(7, ids.size()); } @Test - public void cloneTreeTest(){ + public void cloneTreeTest() { final MapTree tree = TreeUtil.buildSingle(nodeList, "0"); final MapTree cloneTree = tree.cloneTree(); final List ids = new ArrayList<>(); - cloneTree.walk((tr)-> ids.add(tr.getId())); + cloneTree.walk((tr) -> ids.add(tr.getId())); Assertions.assertEquals(7, ids.size()); } @Test - public void filterTest(){ + public void filterTest() { // 经过过滤,丢掉"用户添加"节点 final MapTree tree = TreeUtil.buildSingle(nodeList, "0"); - tree.filter((t)->{ + tree.filter((t) -> { final CharSequence name = t.getName(); return null != name && name.toString().contains("店铺"); }); final List ids = new ArrayList<>(); - tree.walk((tr)-> ids.add(tr.getId())); + tree.walk((tr) -> ids.add(tr.getId())); Assertions.assertEquals(4, ids.size()); } @Test - public void filterNewTest(){ + public void filterNewTest() { final MapTree tree = TreeUtil.buildSingle(nodeList, "0"); // 经过过滤,生成新的树 - final MapTree newTree = tree.filterNew((t)->{ + final MapTree newTree = tree.filterNew((t) -> { final CharSequence name = t.getName(); return null != name && name.toString().contains("店铺"); }); final List ids = new ArrayList<>(); - newTree.walk((tr)-> ids.add(tr.getId())); + newTree.walk((tr) -> ids.add(tr.getId())); Assertions.assertEquals(4, ids.size()); final List ids2 = new ArrayList<>(); - tree.walk((tr)-> ids2.add(tr.getId())); + tree.walk((tr) -> ids2.add(tr.getId())); Assertions.assertEquals(7, ids2.size()); } + + @Test + public void lambdaConfigTest() { + // 配置自定义属性名 为null则取默认值 + LambdaTreeNodeConfig treeNodeConfig = new LambdaTreeNodeConfig<>(); + treeNodeConfig.setChildrenKeyFun(CustomTreeNode::getChildrenNodes); + treeNodeConfig.setIdKeyFun(CustomTreeNode::getNodeId); + treeNodeConfig.setNameKeyFun(CustomTreeNode::getLabel); + treeNodeConfig.setParentIdKeyFun(CustomTreeNode::getParentNodeId); + treeNodeConfig.setWeightKeyFun(CustomTreeNode::getSortNo); + // 最大递归深度 + treeNodeConfig.setDeep(3); + + List> treeNodes = TreeUtil.build(nodeList, "0", treeNodeConfig, new DefaultNodeParser<>()); + Assertions.assertEquals(treeNodes.size(), 2); + MapTree treeNode1 = treeNodes.get(1); + Assertions.assertNotNull(treeNode1); + Assertions.assertNotNull(treeNode1.getConfig()); + Assertions.assertEquals(treeNode1.getChildren().size(), 1); + } + + /** + * 自定义工程树节点对象 + * + * @author Earlman + */ + private class CustomTreeNode { + // 主键ID + private String nodeId; + // 节点名称 + private String label; + // 父级id + private String parentNodeId; + // 排序字段 + private Integer sortNo; + // 子节点 + private List childrenNodes; + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public String getParentNodeId() { + return parentNodeId; + } + + public void setParentNodeId(String parentNodeId) { + this.parentNodeId = parentNodeId; + } + + public Integer getSortNo() { + return sortNo; + } + + public void setSortNo(Integer sortNo) { + this.sortNo = sortNo; + } + + public List getChildrenNodes() { + return childrenNodes; + } + + public void setChildrenNodes(List childrenNodes) { + this.childrenNodes = childrenNodes; + } + } }