diff --git a/CHANGELOG.md b/CHANGELOG.md index f9bb60e37..0c3a4ea97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ * 【core 】 XmlUtil增加xmlToBean和beanToXml方法 * 【db 】 设置全局忽略大小写DbUtil.setCaseInsensitiveGlobal(true)(issue#784@Github) * 【core 】 增加CallerUtil.getCallerMethodName方法 -* 【core 】 Tree增加getParent方法,可以获取父节点 +* 【core 】 Tree增加getParent方法,可以获取父节点,抽象Node接口 ### Bug修复 * 【core 】 修复TypeUtil无法获取泛型接口的泛型参数问题(issue#I1BRFI@Gitee) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/tree/Node.java b/hutool-core/src/main/java/cn/hutool/core/lang/tree/Node.java new file mode 100644 index 000000000..9e8662ca5 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/tree/Node.java @@ -0,0 +1,79 @@ +package cn.hutool.core.lang.tree; + +/** + * 节点接口,提供节点相关的的方法定义 + * + * @param ID类型 + * @author looly + * @since 5.2.4 + */ +public interface Node extends Comparable>{ + /** + * 获取ID + * + * @return ID + */ + T getId(); + + /** + * 设置ID + * + * @param id ID + */ + Node setId(T id); + + /** + * 获取父节点ID + * + * @return 父节点ID + */ + T getParentId(); + + /** + * 设置父节点ID + * + * @param parentId 父节点ID + * @return 父节点ID + */ + Node setParentId(T parentId); + + /** + * 获取节点标签名称 + * + * @return 节点标签名称 + */ + CharSequence getName(); + + /** + * 设置节点标签名称 + * + * @param name 节点标签名称 + * @return this + */ + Node setName(CharSequence name); + + /** + * 获取权重 + * + * @return 权重 + */ + Comparable getWeight(); + + /** + * 设置权重 + * + * @param weight 权重 + * @return this + */ + Node setWeight(Comparable weight); + + @SuppressWarnings({"unchecked", "rawtypes", "NullableProblems"}) + default int compareTo(Node node) { + final Comparable weight = this.getWeight(); + if (null != weight) { + final Comparable weightOther = node.getWeight(); + return weight.compareTo(weightOther); + } + return 0; + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/tree/Tree.java b/hutool-core/src/main/java/cn/hutool/core/lang/tree/Tree.java index 32b409671..3742ea078 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/tree/Tree.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/tree/Tree.java @@ -3,7 +3,6 @@ package cn.hutool.core.lang.tree; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; -import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -14,7 +13,7 @@ import java.util.List; * @author liangbaikai * @since 5.2.1 */ -public class Tree extends LinkedHashMap implements Comparable> { +public class Tree extends LinkedHashMap implements Node { private static final long serialVersionUID = 1L; private TreeNodeConfig treeNodeConfig; @@ -54,21 +53,23 @@ public class Tree extends LinkedHashMap implements Comparable * @since 5.2.4 */ public Tree getNode(T id) { - if (ObjectUtil.equal(id, getId())) { - return this; - } + return TreeUtil.getNode(this, id); + } - // 查找子节点 - Tree node; - for (Tree child : getChildren()) { - node = child.getNode(id); - if (null != node) { - return node; - } - } - - // 未找到节点 - return null; + /** + * 获取所有父节点名称列表 + * + *

+ * 比如有个人在研发1部,他上面有研发部,接着上面有技术中心
+ * 返回结果就是:[研发一部, 研发中心, 技术中心] + * + * @param id 节点ID + * @param includeCurrentNode 是否包含当前节点的名称 + * @return 所有父节点名称列表 + * @since 5.2.4 + */ + public List getParentsName(T id, boolean includeCurrentNode) { + return TreeUtil.getParentsName(getNode(id), includeCurrentNode); } /** @@ -83,17 +84,7 @@ public class Tree extends LinkedHashMap implements Comparable * @since 5.2.4 */ public List getParentsName(boolean includeCurrentNode) { - final List result = new ArrayList<>(); - if (includeCurrentNode) { - result.add(this.getName()); - } - - Tree parent = getParent(); - while (null != parent) { - result.add(parent.getName()); - parent = parent.getParent(); - } - return result; + return TreeUtil.getParentsName(this, includeCurrentNode); } /** @@ -110,55 +101,47 @@ public class Tree extends LinkedHashMap implements Comparable return this; } - /** - * 获取节点ID - * - * @return 节点ID - */ + @Override @SuppressWarnings("unchecked") public T getId() { return (T) this.get(treeNodeConfig.getIdKey()); } - /** - * 设置节点ID - * - * @param id 节点ID - * @return this - */ + @Override public Tree setId(T id) { this.put(treeNodeConfig.getIdKey(), id); return this; } - /** - * 获取父节点ID - * - * @return 父节点ID - */ + @Override @SuppressWarnings("unchecked") public T getParentId() { return (T) this.get(treeNodeConfig.getParentIdKey()); } + @Override public Tree setParentId(T parentId) { this.put(treeNodeConfig.getParentIdKey(), parentId); return this; } + @Override public CharSequence getName() { return (CharSequence) this.get(treeNodeConfig.getNameKey()); } + @Override public Tree setName(CharSequence name) { this.put(treeNodeConfig.getNameKey(), name); return this; } + @Override public Comparable getWeight() { return (Comparable) this.get(treeNodeConfig.getWeightKey()); } + @Override public Tree setWeight(Comparable weight) { this.put(treeNodeConfig.getWeightKey(), weight); return this; @@ -183,15 +166,4 @@ public class Tree extends LinkedHashMap implements Comparable Assert.notEmpty(key, "Key must be not empty !"); this.put(key, value); } - - @SuppressWarnings({"rawtypes", "unchecked", "NullableProblems"}) - @Override - public int compareTo(Tree tree) { - final Comparable weight = this.getWeight(); - if (null != weight) { - final Comparable weightOther = tree.getWeight(); - return weight.compareTo(weightOther); - } - return 0; - } } \ No newline at end of file diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeNode.java b/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeNode.java index 6bec83a02..9dd1ef0d8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeNode.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeNode.java @@ -6,9 +6,10 @@ package cn.hutool.core.lang.tree; * 在你的项目里它可以是部门实体、地区实体等任意类树节点实体 * 类树节点实体: 包含key,父Key.不限于这些属性的可以构造成一颗树的实体对象 * + * @param ID类型 * @author liangbaikai */ -public class TreeNode implements Comparable> { +public class TreeNode implements Node { /** * ID @@ -55,92 +56,47 @@ public class TreeNode implements Comparable> { } - /** - * 获取ID - * - * @return ID - */ + @Override public T getId() { return id; } - /** - * 设置ID - * - * @param id ID - */ - public void setId(T id) { + @Override + public TreeNode setId(T id) { this.id = id; + return this; } - /** - * 获取父节点ID - * - * @return 父节点ID - */ + @Override public T getParentId() { return this.parentId; } - /** - * 设置父节点ID - * - * @param parentId 父节点ID - * @return 父节点ID - */ + @Override public TreeNode setParentId(T parentId) { this.parentId = parentId; return this; } - /** - * 获取节点标签名称 - * - * @return 节点标签名称 - */ + @Override public CharSequence getName() { return name; } - /** - * 设置节点标签名称 - * - * @param name 节点标签名称 - * @return this - */ + @Override public TreeNode setName(CharSequence name) { this.name = name; return this; } - /** - * 获取权重 - * - * @return 权重 - */ + @Override public Comparable getWeight() { return weight; } - /** - * 设置权重 - * - * @param weight 权重 - * @return this - */ + @Override public TreeNode setWeight(Comparable weight) { this.weight = weight; return this; } - - @SuppressWarnings({"unchecked", "rawtypes", "NullableProblems"}) - @Override - public int compareTo(Tree tree) { - final Comparable weight = this.getWeight(); - if (null != weight) { - final Comparable weightOther = tree.getWeight(); - return weight.compareTo(weightOther); - } - return 0; - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeUtil.java index 8effecbe3..06bead429 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/tree/TreeUtil.java @@ -3,7 +3,9 @@ package cn.hutool.core.lang.tree; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.tree.parser.DefaultNodeParser; import cn.hutool.core.lang.tree.parser.NodeParser; +import cn.hutool.core.util.ObjectUtil; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -117,4 +119,61 @@ public class TreeUtil { } } + /** + * 获取ID对应的节点,如果有多个ID相同的节点,只返回第一个。
+ * 此方法只查找此节点及子节点,采用广度优先遍历。 + * + * @param id ID + * @return 节点 + * @since 5.2.4 + */ + public static Tree getNode(Tree node, T id) { + if (ObjectUtil.equal(id, node.getId())) { + return node; + } + + // 查找子节点 + Tree childNode; + for (Tree child : node.getChildren()) { + childNode = child.getNode(id); + if (null != childNode) { + return childNode; + } + } + + // 未找到节点 + return null; + } + + /** + * 获取所有父节点名称列表 + * + *

+ * 比如有个人在研发1部,他上面有研发部,接着上面有技术中心
+ * 返回结果就是:[研发一部, 研发中心, 技术中心] + * + * @param 节点ID类型 + * @param node 节点 + * @param includeCurrentNode 是否包含当前节点的名称 + * @return 所有父节点名称列表,node为null返回空List + * @since 5.2.4 + */ + public static List getParentsName(Tree node, boolean includeCurrentNode) { + final List result = new ArrayList<>(); + if(null == node){ + return result; + } + + if (includeCurrentNode) { + result.add(node.getName()); + } + + Tree parent = node.getParent(); + while (null != parent) { + result.add(parent.getName()); + parent = parent.getParent(); + } + return result; + } + }