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方法
* 【db 】 设置全局忽略大小写DbUtil.setCaseInsensitiveGlobal(true)issue#784@Github
* 【core 】 增加CallerUtil.getCallerMethodName方法
* 【core 】 Tree增加getParent方法可以获取父节点
* 【core 】 Tree增加getParent方法可以获取父节点抽象Node接口
### Bug修复
* 【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.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<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 TreeNodeConfig treeNodeConfig;
@ -54,21 +53,23 @@ public class Tree<T> extends LinkedHashMap<String, Object> implements Comparable
* @since 5.2.4
*/
public Tree<T> getNode(T id) {
if (ObjectUtil.equal(id, getId())) {
return this;
}
return TreeUtil.getNode(this, id);
}
// 查找子节点
Tree<T> node;
for (Tree<T> child : getChildren()) {
node = child.getNode(id);
if (null != node) {
return node;
}
}
// 未找到节点
return null;
/**
* 获取所有父节点名称列表
*
* <p>
* 比如有个人在研发1部他上面有研发部接着上面有技术中心<br>
* 返回结果就是[研发一部, 研发中心, 技术中心]
*
* @param id 节点ID
* @param includeCurrentNode 是否包含当前节点的名称
* @return 所有父节点名称列表
* @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
*/
public List<CharSequence> getParentsName(boolean includeCurrentNode) {
final List<CharSequence> result = new ArrayList<>();
if (includeCurrentNode) {
result.add(this.getName());
}
Tree<T> 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<T> extends LinkedHashMap<String, Object> 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<T> 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<T> setParentId(T parentId) {
this.put(treeNodeConfig.getParentIdKey(), parentId);
return this;
}
@Override
public CharSequence getName() {
return (CharSequence) this.get(treeNodeConfig.getNameKey());
}
@Override
public Tree<T> setName(CharSequence name) {
this.put(treeNodeConfig.getNameKey(), name);
return this;
}
@Override
public Comparable<?> getWeight() {
return (Comparable<?>) this.get(treeNodeConfig.getWeightKey());
}
@Override
public Tree<T> setWeight(Comparable<?> weight) {
this.put(treeNodeConfig.getWeightKey(), weight);
return this;
@ -183,15 +166,4 @@ public class Tree<T> extends LinkedHashMap<String, Object> implements Comparable
Assert.notEmpty(key, "Key must be not empty !");
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.不限于这些属性的可以构造成一颗树的实体对象
*
* @param <T> ID类型
* @author liangbaikai
*/
public class TreeNode<T> implements Comparable<Tree<T>> {
public class TreeNode<T> implements Node<T> {
/**
* ID
@ -55,92 +56,47 @@ public class TreeNode<T> implements Comparable<Tree<T>> {
}
/**
* 获取ID
*
* @return ID
*/
@Override
public T getId() {
return id;
}
/**
* 设置ID
*
* @param id ID
*/
public void setId(T id) {
@Override
public TreeNode<T> 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<T> setParentId(T parentId) {
this.parentId = parentId;
return this;
}
/**
* 获取节点标签名称
*
* @return 节点标签名称
*/
@Override
public CharSequence getName() {
return name;
}
/**
* 设置节点标签名称
*
* @param name 节点标签名称
* @return this
*/
@Override
public TreeNode<T> setName(CharSequence name) {
this.name = name;
return this;
}
/**
* 获取权重
*
* @return 权重
*/
@Override
public Comparable<?> getWeight() {
return weight;
}
/**
* 设置权重
*
* @param weight 权重
* @return this
*/
@Override
public TreeNode<T> 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;
}
}

View File

@ -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相同的节点只返回第一个<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;
}
}