正确地从树中删除节点
我有以下函数来修剪树数据结构:
public static void pruneTree(final ConditionTreeNode treeNode) {
final List<ConditionTreeNode> subTrees = treeNode.getSubTrees();
for (ConditionTreeNode current : subTrees) {
pruneTree(current);
}
if(subTrees.isEmpty()) {
final ConditionTreeNode parent = treeNode.getParent();
parent.removeConditionTreeNode(treeNode);
}
if (treeNode.isLeaf()) {
//this is the base case
if (treeNode.isPrunable()) {
final ConditionTreeNode parent = treeNode.getParent();
parent.removeConditionTreeNode(treeNode);
}
return;
}
}
我想知道修剪它的最佳方法是什么。我当前收到 ConcurrentModificationExceptions,并且我读到您可以复制集合,然后删除原始集合,或者从迭代器中删除。有人可以帮助我了解我需要做什么才能使此方法发挥作用吗?
I have the following function that prunes a tree data structure :
public static void pruneTree(final ConditionTreeNode treeNode) {
final List<ConditionTreeNode> subTrees = treeNode.getSubTrees();
for (ConditionTreeNode current : subTrees) {
pruneTree(current);
}
if(subTrees.isEmpty()) {
final ConditionTreeNode parent = treeNode.getParent();
parent.removeConditionTreeNode(treeNode);
}
if (treeNode.isLeaf()) {
//this is the base case
if (treeNode.isPrunable()) {
final ConditionTreeNode parent = treeNode.getParent();
parent.removeConditionTreeNode(treeNode);
}
return;
}
}
and I want to know what the best way to prune this is. I'm getting ConcurrentModificationExceptions currently, and I've read that you can copy the collection, and remove the original -- or remove from an iterator. Can someone help me understand what I need to do inorder for this method to work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是,您正在迭代节点集合,并且在某些情况下从递归调用内的集合中删除实际项目。您可以从递归调用中返回一个布尔标志来指示要删除的实际项目,然后通过
Iterator.remove()
删除它(您需要将 foreach 循环更改为迭代器循环使这成为可能)。用其唯一的子节点替换实际项目比较棘手 - 您可以定义一个自定义类以从递归方法调用中返回更多信息,但这开始变得尴尬。或者您可以考虑使用堆栈等循环来替换递归调用。
The problem is, you are iterating through the collection of nodes and in some cases removing the actual item from the collection inside the recursive call. You could instead return a boolean flag from the recursive call to sign that the actual item is to be removed, then remove it via
Iterator.remove()
(you need to change the foreach loop to an iterator loop to make this possible).Replacing the actual item with its only subnode is trickier - you could define a custom class to return more info from the recursive method call, but it starts to become awkward. Or you may consider replacing the recursive call with a loop using e.g. a stack.