简体   繁体   中英

Java - ConcurrentModificationException with recursive method and nested iterators

I have an assignment to write a Java program that will read in a context-free grammar and return the FirstSets of all non-terminals. I've taken a recursive approach with my FirstSet() method:

public static ArrayList<String> firstSet(String nonTerminal){
    ArrayList<String> first = new ArrayList<String>();
    //Find initial elements of FirstSet
    for(String[] current : prodRules) {
        if (current[0].equals(nonTerminal)){ //if the production rule is for that non-terminal
            if(current.length > 2) {
                first.add(current[2]);          //first element after "-->" is added to FirstSet
            } else
                first.add("eps");
        }
    }
    //Add the FirstSet of each element in the initial FirstSet
    ArrayList<String> copy = first; //to avoid ConcurrentModificationException
    Iterator<String> it1 = copy.iterator();
    while(it1.hasNext()) { //recursively find each FirstSet of the initial elements
        String s = it1.next();
        System.out.println("FIRST("+s+")={");
        ArrayList<String> nestedFS = firstSet(s);
        Iterator<String> it2 = nestedFS.iterator();
        while(it2.hasNext()) {
            String f = it2.next();
            if(!first.contains(f))
                first.add(f);
            System.out.print(" "+f+" ");
        }
        System.out.print("}");
    }
    return first;
}

However, I keep getting a ConcurrentModificationException error for the lines:

String s = it1.next();

ArrayList<String> nestedFS = firstSet(s);

As far as I can tell, I'm not modifying any lists that I am currently iterating through. Rather, I am iterating through copies. I'm not concerned with redundant memory usage or speed, I just need this to work.

Any clue as to what I'm doing wrong here? Any help is much appreciated.

Create the copy of ArrayList first using CopyOnWriteArrayList which avoids the ConcurrentModificationException.

    ArrayList<String> copy = first; //replace this line with 
    CopyOnWriteArrayList<String> copy= new CopyOnWriteArrayList<String>(first);

ArrayList is not threadsafe and need to implement the thread safety, instead, we can use CopyOnWriteArrayList which is thread safe.

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