递归遍历树时出现 ConcurrentModificationError

问题描述

在递归遍历树结构以计算整个物料清单的重量和体积时,我遇到了 ConcurrentModificationException。我的伪代码方法

  1. 查询初始化:将根节点添加到节点列表中并检查它是否有任何子节点。
  2. 进度文档:将节点标记为已访问。
  3. 查询子节点:检查子节点,如果存在,则使用升级标志添加到所有节点。
  4. 递归遍历:递归遍历列表,直到找不到更多的子元素。

我曾尝试使用迭代器来扩展该节点数组,但遇到了同样的问题。在这里慢慢没有想法,我很感激任何提示

注意:请原谅我粘贴我的问题而不说明所有上下文以提高可读性。如果您需要更多信息,请告诉我。

// Initialization
List<Node> allNodes = new ArrayList<>();
allNodes.add(new Node(input,input,false)     // (1)
int counter = 0;

// Method call
getAllNodes(allNodes);

// Query parent for child elements
public void getAllNodes(List<Node> nodes){
    for (Node node : nodes) {   
        if (!node.isVisited()) {      // (2)
            node.setVisited(true);
            String parentId = node.getId();
            Product product = QueryUtil.getFirstByIdNo(ctx,parentId,Product.class);
            if (isComposite(product)) {
                Iterable<Product.Row> rows = product.table().getRows();   // (3)
                for (Product.Row row : rows) {
                    allNodes.add(new Node(parentId,row.getProductListElem().getIdno(),++counter,false));
                    --counter;
                }
                ++counter;
               // Recursive query of all node elements
                getAllNodes(allNodes);        // (4)
            }
        } 
    }
}

//Node Bean with getters,setters,constructor,toString
@Data
class Node {
    String parent;
    String id; 
    int level;
    boolean visited;
}

解决方法

您收到错误是因为您正在尝试修改您正在迭代(阅读)的列表。这在 JAVA 中是不允许的。 [更多解释请查看here]

为了避免这种情况,您可以为您的列表获取一个迭代器,然后循环遍历它,但这对于您上面发布的代码来说似乎不是一个很好的选择。因此,我建议使用 List<Node> allNodes = new CopyOnWriteArrayList<>(); 而不是 List<Node> allNodes = new ArrayList<>()