Search code examples
javalistexceptionarraylistconcurrentmodification

why am i getting a java.util.ConcurrentModificationException in the advanced for loop?


Unlike other exception scenarios I've seen, the exception I keep getting happens at the for loop I commented below with //where it goes wrong//. And in my implementation, the List partialR doesn't change while I iterate it, so I am really confused.

public class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        result.add(new ArrayList<Integer>());
        return permute(nums, 0, result);
    }

    public List<List<Integer>> permute(int[] nums, int i, List<List<Integer>> result){
        if (i == nums.length){
            return result;
        }
        int num = nums[i];
        List<List<Integer>> partialR = permute(nums, i+1, result);
        System.out.println("partialR"+partialR);
        for (List<Integer> t : partialR){***//where it goes wrong//***
            System.out.println("t"+t);
            for (int j=0; j <= t.size(); j++){
                System.out.println("j="+j);
                List<Integer> subs = insert(t,num,j);
                result.add(subs);
                System.out.println("result"+result);
            }
        }
        System.out.println("result");
        return result;
    }
    public List<Integer> insert(List<Integer> t, int num, int j){
        List<Integer> temp = new ArrayList<>();       
        if (j == 0){
            temp.add(num);
            temp.addAll(t);
            System.out.println("temp"+temp);
            return temp;
        }else if(j == t.size()){
            temp.addAll(t);
            temp.add(num);
            return temp;
        }
        List<Integer> temp1 = new ArrayList<Integer> (t.subList(j,t.size()-1));
        List<Integer> temp2 = new ArrayList<Integer> (t.subList(0,j-1));
        temp.addAll(temp1);
        temp.add(num);
        temp.addAll(temp2);
        return temp;
    }
}

Solution

  • You pass result to permute, and it returns result. So when you do this:

    List<List<Integer>> partialR = permute(nums, i+1, result);
    

    Now partialR points to result too. And then when you iterate over it with for (List<Integer> t : partialR), you modify result when you do result.add(subs). So in effect, you're modifying result while you're iterating over it, which is not allowed by the fail-fast behavior of iterators in Java. (You can read more about this in the javadoc of ConcurrentModificationException.)

    You could fix this by creating a new ArrayList here:

    List<List<Integer>> partialR = new ArrayList<>(permute(nums, i + 1, result));
    

    There are some other mistakes too, unrelated to the concurrent modification. In insert, the range of values to create temp1 and temp2 are incorrect. Corrected and simplified, you can write:

    List<Integer> temp1 = t.subList(j, t.size());
    List<Integer> temp2 = t.subList(0, j);