This commit is contained in:
Looly 2020-03-18 17:18:38 +08:00
parent 4663e0d175
commit d330c489b3
5 changed files with 177 additions and 111 deletions

View File

@ -13,7 +13,7 @@
* 【core 】 XmlUtil增加xmlToBean和beanToXml方法 * 【core 】 XmlUtil增加xmlToBean和beanToXml方法
* 【db 】 设置全局忽略大小写DbUtil.setCaseInsensitiveGlobal(true)issue#784@Github * 【db 】 设置全局忽略大小写DbUtil.setCaseInsensitiveGlobal(true)issue#784@Github
* 【core 】 增加CallerUtil.getCallerMethodName方法 * 【core 】 增加CallerUtil.getCallerMethodName方法
* 【core 】 Tree增加getParent方法可以获取父节点 * 【core 】 Tree增加getParent方法可以获取父节点抽象Node接口
### Bug修复 ### Bug修复
* 【core 】 修复TypeUtil无法获取泛型接口的泛型参数问题issue#I1BRFI@Gitee * 【core 】 修复TypeUtil无法获取泛型接口的泛型参数问题issue#I1BRFI@Gitee

View File

@ -0,0 +1,79 @@
package cn.hutool.core.lang.tree;
/**
* 节点接口提供节点相关的的方法定义
*
* @param <T> ID类型
* @author looly
* @since 5.2.4
*/
public interface Node<T> extends Comparable<Node<T>>{
/**
* 获取ID
*
* @return ID
*/
T getId();
/**
* 设置ID
*
* @param id ID
*/
Node<T> setId(T id);
/**
* 获取父节点ID
*
* @return 父节点ID
*/
T getParentId();
/**
* 设置父节点ID
*
* @param parentId 父节点ID
* @return 父节点ID
*/
Node<T> setParentId(T parentId);
/**
* 获取节点标签名称
*
* @return 节点标签名称
*/
CharSequence getName();
/**
* 设置节点标签名称
*
* @param name 节点标签名称
* @return this
*/
Node<T> setName(CharSequence name);
/**
* 获取权重
*
* @return 权重
*/
Comparable<?> getWeight();
/**
* 设置权重
*
* @param weight 权重
* @return this
*/
Node<T> 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;
}
}

View File

@ -3,7 +3,6 @@ package cn.hutool.core.lang.tree;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -14,7 +13,7 @@ import java.util.List;
* @author liangbaikai * @author liangbaikai
* @since 5.2.1 * @since 5.2.1
*/ */
public class Tree<T> extends LinkedHashMap<String, Object> implements Comparable<Tree<T>> { public class Tree<T> extends LinkedHashMap<String, Object> implements Node<T> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private TreeNodeConfig treeNodeConfig; private TreeNodeConfig treeNodeConfig;
@ -54,21 +53,23 @@ public class Tree<T> extends LinkedHashMap<String, Object> implements Comparable
* @since 5.2.4 * @since 5.2.4
*/ */
public Tree<T> getNode(T id) { public Tree<T> getNode(T id) {
if (ObjectUtil.equal(id, getId())) { return TreeUtil.getNode(this, id);
return this; }
}
// 查找子节点 /**
Tree<T> node; * 获取所有父节点名称列表
for (Tree<T> child : getChildren()) { *
node = child.getNode(id); * <p>
if (null != node) { * 比如有个人在研发1部他上面有研发部接着上面有技术中心<br>
return node; * 返回结果就是[研发一部, 研发中心, 技术中心]
} *
} * @param id 节点ID
* @param includeCurrentNode 是否包含当前节点的名称
// 未找到节点 * @return 所有父节点名称列表
return null; * @since 5.2.4
*/
public List<CharSequence> getParentsName(T id, boolean includeCurrentNode) {
return TreeUtil.getParentsName(getNode(id), includeCurrentNode);
} }
/** /**
@ -83,17 +84,7 @@ public class Tree<T> extends LinkedHashMap<String, Object> implements Comparable
* @since 5.2.4 * @since 5.2.4
*/ */
public List<CharSequence> getParentsName(boolean includeCurrentNode) { public List<CharSequence> getParentsName(boolean includeCurrentNode) {
final List<CharSequence> result = new ArrayList<>(); return TreeUtil.getParentsName(this, includeCurrentNode);
if (includeCurrentNode) {
result.add(this.getName());
}
Tree<T> parent = getParent();
while (null != parent) {
result.add(parent.getName());
parent = parent.getParent();
}
return result;
} }
/** /**
@ -110,55 +101,47 @@ public class Tree<T> extends LinkedHashMap<String, Object> implements Comparable
return this; return this;
} }
/** @Override
* 获取节点ID
*
* @return 节点ID
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T getId() { public T getId() {
return (T) this.get(treeNodeConfig.getIdKey()); return (T) this.get(treeNodeConfig.getIdKey());
} }
/** @Override
* 设置节点ID
*
* @param id 节点ID
* @return this
*/
public Tree<T> setId(T id) { public Tree<T> setId(T id) {
this.put(treeNodeConfig.getIdKey(), id); this.put(treeNodeConfig.getIdKey(), id);
return this; return this;
} }
/** @Override
* 获取父节点ID
*
* @return 父节点ID
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T getParentId() { public T getParentId() {
return (T) this.get(treeNodeConfig.getParentIdKey()); return (T) this.get(treeNodeConfig.getParentIdKey());
} }
@Override
public Tree<T> setParentId(T parentId) { public Tree<T> setParentId(T parentId) {
this.put(treeNodeConfig.getParentIdKey(), parentId); this.put(treeNodeConfig.getParentIdKey(), parentId);
return this; return this;
} }
@Override
public CharSequence getName() { public CharSequence getName() {
return (CharSequence) this.get(treeNodeConfig.getNameKey()); return (CharSequence) this.get(treeNodeConfig.getNameKey());
} }
@Override
public Tree<T> setName(CharSequence name) { public Tree<T> setName(CharSequence name) {
this.put(treeNodeConfig.getNameKey(), name); this.put(treeNodeConfig.getNameKey(), name);
return this; return this;
} }
@Override
public Comparable<?> getWeight() { public Comparable<?> getWeight() {
return (Comparable<?>) this.get(treeNodeConfig.getWeightKey()); return (Comparable<?>) this.get(treeNodeConfig.getWeightKey());
} }
@Override
public Tree<T> setWeight(Comparable<?> weight) { public Tree<T> setWeight(Comparable<?> weight) {
this.put(treeNodeConfig.getWeightKey(), weight); this.put(treeNodeConfig.getWeightKey(), weight);
return this; return this;
@ -183,15 +166,4 @@ public class Tree<T> extends LinkedHashMap<String, Object> implements Comparable
Assert.notEmpty(key, "Key must be not empty !"); Assert.notEmpty(key, "Key must be not empty !");
this.put(key, value); this.put(key, value);
} }
@SuppressWarnings({"rawtypes", "unchecked", "NullableProblems"})
@Override
public int compareTo(Tree<T> tree) {
final Comparable weight = this.getWeight();
if (null != weight) {
final Comparable weightOther = tree.getWeight();
return weight.compareTo(weightOther);
}
return 0;
}
} }

View File

@ -6,9 +6,10 @@ package cn.hutool.core.lang.tree;
* 在你的项目里它可以是部门实体地区实体等任意类树节点实体 * 在你的项目里它可以是部门实体地区实体等任意类树节点实体
* 类树节点实体: 包含key父Key.不限于这些属性的可以构造成一颗树的实体对象 * 类树节点实体: 包含key父Key.不限于这些属性的可以构造成一颗树的实体对象
* *
* @param <T> ID类型
* @author liangbaikai * @author liangbaikai
*/ */
public class TreeNode<T> implements Comparable<Tree<T>> { public class TreeNode<T> implements Node<T> {
/** /**
* ID * ID
@ -55,92 +56,47 @@ public class TreeNode<T> implements Comparable<Tree<T>> {
} }
/** @Override
* 获取ID
*
* @return ID
*/
public T getId() { public T getId() {
return id; return id;
} }
/** @Override
* 设置ID public TreeNode<T> setId(T id) {
*
* @param id ID
*/
public void setId(T id) {
this.id = id; this.id = id;
return this;
} }
/** @Override
* 获取父节点ID
*
* @return 父节点ID
*/
public T getParentId() { public T getParentId() {
return this.parentId; return this.parentId;
} }
/** @Override
* 设置父节点ID
*
* @param parentId 父节点ID
* @return 父节点ID
*/
public TreeNode<T> setParentId(T parentId) { public TreeNode<T> setParentId(T parentId) {
this.parentId = parentId; this.parentId = parentId;
return this; return this;
} }
/** @Override
* 获取节点标签名称
*
* @return 节点标签名称
*/
public CharSequence getName() { public CharSequence getName() {
return name; return name;
} }
/** @Override
* 设置节点标签名称
*
* @param name 节点标签名称
* @return this
*/
public TreeNode<T> setName(CharSequence name) { public TreeNode<T> setName(CharSequence name) {
this.name = name; this.name = name;
return this; return this;
} }
/** @Override
* 获取权重
*
* @return 权重
*/
public Comparable<?> getWeight() { public Comparable<?> getWeight() {
return weight; return weight;
} }
/** @Override
* 设置权重
*
* @param weight 权重
* @return this
*/
public TreeNode<T> setWeight(Comparable<?> weight) { public TreeNode<T> setWeight(Comparable<?> weight) {
this.weight = weight; this.weight = weight;
return this; 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;
}
} }

View File

@ -3,7 +3,9 @@ package cn.hutool.core.lang.tree;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.parser.DefaultNodeParser; import cn.hutool.core.lang.tree.parser.DefaultNodeParser;
import cn.hutool.core.lang.tree.parser.NodeParser; 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.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -117,4 +119,61 @@ public class TreeUtil {
} }
} }
/**
* 获取ID对应的节点如果有多个ID相同的节点只返回第一个<br>
* 此方法只查找此节点及子节点采用广度优先遍历
*
* @param id ID
* @return 节点
* @since 5.2.4
*/
public static <T> Tree<T> getNode(Tree<T> node, T id) {
if (ObjectUtil.equal(id, node.getId())) {
return node;
}
// 查找子节点
Tree<T> childNode;
for (Tree<T> child : node.getChildren()) {
childNode = child.getNode(id);
if (null != childNode) {
return childNode;
}
}
// 未找到节点
return null;
}
/**
* 获取所有父节点名称列表
*
* <p>
* 比如有个人在研发1部他上面有研发部接着上面有技术中心<br>
* 返回结果就是[研发一部, 研发中心, 技术中心]
*
* @param <T> 节点ID类型
* @param node 节点
* @param includeCurrentNode 是否包含当前节点的名称
* @return 所有父节点名称列表node为null返回空List
* @since 5.2.4
*/
public static <T> List<CharSequence> getParentsName(Tree<T> node, boolean includeCurrentNode) {
final List<CharSequence> result = new ArrayList<>();
if(null == node){
return result;
}
if (includeCurrentNode) {
result.add(node.getName());
}
Tree<T> parent = node.getParent();
while (null != parent) {
result.add(parent.getName());
parent = parent.getParent();
}
return result;
}
} }