我需要获取树节点的所有后代。为此,我编写了一个需要帮助功能的功能。当我想要得到结果时,我得到了以下错误:
at java.base / java.util.ArrayList $ Itr.checkForComodification(未知源) 在java.base / java.util.ArrayList $ Itr.next(未知来源)
我已经犯了这个错误,这就是为什么我为每种方法创建不同的列表的原因:子代,后代,祖先,元素和位置。现在我到处都有错误。
public List<Position<E>> descendants(Position<E> p) throws InvalidPositionException {
if(p == null || isEmpty())
throw new InvalidPositionException();
// remove all positions from list
descendantList.removeAll(descendantList);
return descendantsList(p);
}
public List<Position<E>> descendantsList(Position<E> p) {
if(isInternal(p)) {
// add child to list and check if the child has also children
for(Position<E> child : children(p)) {
descendantList.add(child);
// if child has also children
if(isInternal(child))
descendantsList(child);
}
}
return descendantList;
}
children函数如下所示:
public List<Position<E>> children(Position<E> p) throws InvalidPositionException {
if(p == null || isEmpty())
throw new InvalidPositionException();
else {
BinaryTreeNode<E> node = (BinaryTreeNode<E>) p;
childrenList.removeAll(childrenList);
// add left child first
if(node.leftChild != null)
childrenList.add(node.leftChild);
if(node.rightChild != null)
childrenList.add(node.rightChild);
return childrenList;
}
}
为此,我创建了不同的列表:
- ArrayList for children: childrenList
- ArrayList for descendants: descendantsList
如何解决此错误?
编辑:我用clear替换了所有removeAll。它适用于此方法的后代,但作为示例,我的height方法仍然存在相同的错误:
public int height() throws EmptyTreeException {
if(isEmpty())
throw new EmptyTreeException();
else
return heightOf(root);
}
private int heightOf(Position<E> p) {
if(isExternal(p))
return 0;
else {
int h = 0;
for(Position<E> child : children(p)) {
h = Math.max(h,heightOf(child));
}
return h + 1;
}
}
答案 0 :(得分:0)
请勿使用removeAll(childrenList)
。使用clear()
。首先,它更快,其次,这可能是您出错的地方。 removeAll()
逐步浏览提供的Collection,并删除Collection中调用它的元素。在您的情况下,这是相同的集合。
编辑:好的。我知道发生了什么事。我必须自己实现它才能看到。
基本上,您会打height(root)
。这会遍历树并找到每个节点的heightOf
并将其返回。
在您的heightOf
方法中,您有一个使用递归的for循环。
for循环调用children(node)
清除列表childrenList
,然后重新填充列表。
问题是在第一次迭代childrenList
中分配了一些值。然后,您再次调用heightOf
,同时仍然引用位于Position<E>
中的childrenList
(您将此孩子称为Position<E>
)。在子节点上再次调用heightOf
时,将再次修改childrenList
。由于您仍然持有Position<E>
中对childrenList
的引用,并且尝试删除或更改此引用,因此您会得到ConcurrentModificationException
。
您可以通过将children
方法更改为类似方法来解决此问题:
public List<Position<E>> children(Position<E> p) throws InvalidPositionException {
List<Position<E>> returnList = new ArrayList<>();
if(p == null || isEmpty()) {
throw new InvalidPositionException();
}else {
BinaryTreeNode<E> node = (BinaryTreeNode<E>) p;
// add left child first
if(node.leftChild != null) {
returnList.add(node.leftChild);
}
if(node.rightChild != null) {
returnList.add(node.rightChild);
}
return returnList;
}
}
为了维护树中所有节点的childrenList
,您可能需要创建一个新方法,然后仅调用该方法一次。该方法看起来与您当前的children
方法非常相似,但是您可以在每个节点的左,右子节点上递归调用它。
答案 1 :(得分:0)
我这样解决了这个问题: 我为使用子级列表的每种方法创建了一个新列表。这样,我没有得到以下错误:
在java.base / java.util.ArrayList $ Itr.checkForComodification(未知源)在java.base / java.util.ArrayList $ Itr.next(未知源)