如何解决数组列表中未知来源的问题?

时间:2019-04-29 14:17:08

标签: java for-loop arraylist

我需要获取树节点的所有后代。为此,我编写了一个需要帮助功能的功能。当我想要得到结果时,我得到了以下错误:

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;
    }
}

2 个答案:

答案 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(未知源)