Java实现Node类构建父子树 统计指定节点所有后代节点方案
问题背景
需要实现Node类构建多叉树形结构,基础规则为每个节点可持有多个子节点,通过实例化多个节点即可组装为完整树,示例结构如下:
node1 (根节点) 子节点为node2、node3 node2 子节点为node4、node5
核心需求为两点:
- 修复现有代码方法签名与调用不匹配的编译问题
- 实现查询指定节点下所有后代节点的功能(以上述示例为例,node1的后代共4个:直接子节点node2、node3,加上node2的子节点node4、node5)
现有给出的Node类、树构建业务逻辑、CSV数据源存在逻辑bug,无法正常运行。
现有代码核心问题
findNodeByName方法仅提供双参数签名,但业务代码中大量调用单参数版本,直接报编译错误findNodeByName递归逻辑存在隐患:遍历子节点时依赖当前实例的children属性,而非传入的遍历起始节点的子节点集合,跨节点调用时会出现查找失效- 未实现全量后代节点查询、统计的相关逻辑
- 存在无用导入,空描述字段未做判空处理,容易触发空指针
- CSV解析逻辑未处理引号包裹字段、Windows换行符
\r,容易出现字段解析错误
修正实现方案
1. 修正Node类
删除无用导入,修复查找方法逻辑,新增后代节点收集方法,最终代码如下:
package ex1; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class Node { private String name; private String description; private ArrayList<Node> children = new ArrayList<>(); Node(String name, String description){ this.name = name; // 空描述默认赋值为空串,避免空指针 this.description = description == null ? "" : description; } private void setName(String name){ this.name = name; } private void setDescription(String description) { this.description = description == null ? "" : description; } public void addChildren(Node child) { this.children.add(child); } public String getName() { return this.name; } public String getDescription() { return this.description; } public boolean hasDescription() { return !description.isEmpty(); } public Collection<Node> getChildren() { return this.children; } // 单参数重载方法,匹配业务层调用逻辑,默认从当前节点开始查找 public Node findNodeByName(String name){ return findNodeByName(name, this); } // 内部递归查找逻辑,遍历指定起始节点的所有子树 private Node findNodeByName(String name, Node t){ if(t.getName().equals(name)){ return t; } for(Node c: t.getChildren()){ Node ret = c.findNodeByName(name, c); if(ret != null){ return ret; } } return null; } // 获取当前节点下所有后代节点(包含所有层级的子节点) public List<Node> getAllDescendants(){ List<Node> descendants = new ArrayList<>(); collectDescendants(this, descendants); return descendants; } // 深度优先递归收集所有后代 private void collectDescendants(Node current, List<Node> collector){ for (Node child : current.getChildren()) { collector.add(child); collectDescendants(child, collector); } } // 统计后代节点总数量 public int countAllDescendants(){ return getAllDescendants().size(); } // 要求保留的方法,不做修改 private String toString(int indentNo) { String indent = "\t".repeat(indentNo); StringBuffer b = new StringBuffer(); b.append(indent); b.append(getClass().getSimpleName() + " '" + getName() + "' "); if (hasDescription()) { b.append("(description: " + getDescription() + ")"); } b.append("\n"); for (Node node : getChildren()) { b.append(node.toString(indentNo + 1)); } return b.toString(); } @Override public String toString() { return toString(0); } }
2. 修正树构建业务逻辑
调整CSV解析逻辑,处理换行符、引号字段问题,适配修正后的Node类方法:
Path path = Path.of(pathname); String fileContent = null; try { fileContent = Files.readString(path); // 替换Windows换行符,避免字段携带多余\r字符 fileContent = fileContent.replace("\r", ""); } catch (IOException e) { throw new RuntimeException(e); } List<String> lines = new ArrayList<>(Arrays.asList(fileContent.split("\n"))); // 过滤空行 lines.removeIf(String::isBlank); // split传-1保留空字段,避免数组长度不足 String[] firstLine = lines.get(0).split(",", -1); // 去掉描述字段包裹的引号 String rootName = firstLine[0]; String rootDesc = firstLine[1].replace("\"", ""); Node parentNode = new Node(rootName, rootDesc); lines.remove(0); Node tmpNode; for(String line: lines) { String[] params = line.split(",", -1); String nodeName = params[0]; String nodeDesc = params[1].replace("\"", ""); String parentName = params[2]; // 校验:父节点必须存在、新节点名不重复 if (parentNode.findNodeByName(parentName)==null || parentNode.findNodeByName(nodeName)!=null){ throw new IOException("节点配置非法:父节点不存在或节点名重复"); } tmpNode = parentNode.findNodeByName(parentName); tmpNode.addChildren(new Node(nodeName,nodeDesc)); }
功能验证
基于给出的CSV数据源构建完成树后,可直接调用方法验证功能:
- 根节点
uni调用countAllDescendants()返回5,对应5个后代节点:firstyear、secondyear、analysis、db、ai - 节点
firstyear调用countAllDescendants()返回2,对应子节点analysis、db - 节点
secondyear调用countAllDescendants()返回1,对应子节点ai - 任意节点调用
getAllDescendants()可直接获取所有后代节点的实例列表,可按需做后续过滤、遍历操作。
内容的提问来源于stack exchange,提问作者Shark44
相关产品推荐
相关产品推荐

