一下所有都是基于没有维护节点路径的,如果你维护了treePath,所有的操作都会非常节点
存储:我们以最简单的表设定
- id # 节点id
- name # 节点名
- parentId # 父id
节点对象:
如果有其他的属性,集成这个基础的节点对象就好了。
@Data
public class BaseTreeNode {
private Long id;
private Long parentId;
private String name;
private List<BaseTreeNode> child;
}
树的操作
通常树的操作有遍历,搜索,基于封装的概念,我们可以把一些基础操作封装在这个对象种
生成树
/**
* 节点map k是id v是节点对象
*/
public static BaseTreeNode buildTree(Map<Long, ? extends BaseTreeNode> tree) {
BaseTreeNode rootV = new BaseTreeNode();
rootV.setChild(new ArrayList<>());
tree.forEach((k, v) -> {
BaseTreeNode pnode = tree.get(v.getParentId());
if (pnode == null && v.getParentId() != 0) {
// 垃圾节点
return;
}
if (pnode == null && v.getParentId() == 0) {
rootV.getChild().addNode(v);
return;
}
if (CollectionUtils.isEmpty(pnode.getChild())) {
pnode.setChild(new ArrayList<>());
}
pnode.getChild().addNode(v);
});
return rootV;
}
搜索任意节点,并将节点树展示出来
1:匹配到叶子节点,则从根节点展示到叶子节点
2:匹配到非叶节点,则将根节点展示到该子树
如图:查询b2节点,那么应该显示如下黄色的节点
/**
* 匹配节点树
* @param node
* @param trees
* @param query
* @return
*/
public static BaseTreeNode matchQuery(BaseTreeNode node, List<BaseTreeNode> trees, String query) {
List<BaseTreeNode> matchNodes = new ArrayList<>();
// 获取匹配的节点
matchNode(node, matchNodes, query);
// 深拷贝
final List<BaseTreeNode> baseTreeNodes = JSONObject.parseArray(JSONObject.toJSONString(trees), BaseTreeNode.class);
final Map<Long, BaseTreeNode> map = baseTreeNodes.stream().collect(Collectors.toMap(BaseTreeNode::getId, Function.identity()));
BaseTreeNode root = new BaseTreeNode();
for (BaseTreeNode n : matchNodes) {
root = traceRoot(n, map);
}
return root;
}
private static void matchNode(BaseTreeNode node, List<BaseTreeNode> trees, String query) {
if (node == null) {
return;
}
if (node.getName().contains(query)) {
trees.add(node);
return;
}
if (CollectionUtils.isNotEmpty(node.getChild())) {
node.getChild().forEach(n -> {
matchNode(n, trees, query);
});
}
}
public static BaseTreeNode traceRoot(BaseTreeNode node, Map<Long, ? extends BaseTreeNode> tree) {
final Long pid = node.getParentId();
if (pid == null || pid == 0) {
return node;
}
final BaseTreeNode pnode = tree.get(pid);
if (CollectionUtils.isEmpty(pnode.getChild())) {
pnode.setChild(new BaseTreeList());
}
pnode.getChild().add(node);
return traceRoot(pnode, tree);
}