简体   繁体   中英

ConcurrentModificationError when traversing a tree recursively

When traversing a tree structure recursively in order to calculate weights and volumes for an entire bill of materials, I run into a ConcurrentModificationException. My approach in pseudocode:

  1. Query initialization: add root node to list of nodes and check if it has any childs.
  2. Progress documentation: Flag the node as visited.
  3. Query childs: Checking for child nodes and if present add to allNodes with a level up flag.
  4. Recursive traversal: Recursively traverse list until no more child elements are found.

I have tried to use iterators to allow myself to expand that array of nodes but ran into the same problem. Slowly running out of ideas here I am grateful for any hint.

NOTE: please forgive me to paste my problem not stating all the context for better readability. Let me know if you need more info.

// Initialization
List<Node> allNodes = new ArrayList<>();
allNodes.add(new Node(input, input, 0, 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;
}

You are getting the error because you are trying to modify the list that you are iterating(reading) over. And this is not allowed in JAVA. [for more explanation check here]

To avoid this you can either get an iterator for your list and then loop over it, but that does not seem like a very good option for the code you have posted above. Thus, I'll recommend using List<Node> allNodes = new CopyOnWriteArrayList<>(); instead of List<Node> allNodes = new ArrayList<>() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM