递归地将元素添加到ArrayList时发生并发修改异常

问题描述

在将元素递归添加到ArrayList时获取并发修改异常。

import java.util.*;

public class Hello {

    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(system.in);
        String str = sc.next();
        
        System.out.println(gss(str));
    }

    public static ArrayList<String> gss(String str) {
        if(str.length() == 0){
            ArrayList<String> list = new ArrayList<String>();
            list.add("");
            return list;
        }
        
        ArrayList<String> list = gss(str.substring(1));
        for(String temp : list){
            list.add(str.charat(0)+temp);  // Problem  
        }
        
        return list;
    }

}

解决方法

解决方案:只需在每个调用堆栈处形成新的ArrayList并返回它即可。

import java.io.*;

import java.util.*;

public class Main {

public static void main(String[] args) throws Exception {
    Scanner sc = new Scanner(System.in);
    String str = sc.next();
    
    System.out.println(gss(str));
}

public static ArrayList<String> gss(String str) {
    if(str.length() == 0){
        ArrayList<String> list = new ArrayList<String>();
        list.add("");
        return list;
    }
    
    ArrayList<String> list = gss(str.substring(1));
    ArrayList<String> listToReturn = new ArrayList<>();
    
    for(String temp : list){
        listToReturn.add(temp);
    }
    for(String temp : list){
        listToReturn.add(str.charAt(0) + temp);    
    }
    
    return listToReturn;
}

}

我最近遇到了这个blog

其中说,它使用一个名为modCount的瞬态变量,该变量跟踪列表在结构上被修改的次数。结构修改是那些会更改列表大小的修改,它们可能会影响迭代的进度并可能产生错误的结果。 IteratorListIterator都使用此字段来检测意外更改。在结构上修改List的List的其他方法也使用此方法,例如add(),remove()

原因ConcurrentModficationException的真正原因与modCount不一致。当您在ArrayList上进行迭代时,Iterator的next()方法将跟踪modCount。如果您通过添加或删除元素来修改集合,则modCount将发生变化,并且与预期的modCount不匹配,因此Iterator会抛出ConcurrentModificationException