简体   繁体   中英

Concurrent modification excpetion with iterator adding to arraylist

I'm trying to add an Integer to an array list using and iterator. It crashes at the third call to .next() of the iterator. Here is the stack trace and code

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:886)
    at java.util.ArrayList$Itr.next(ArrayList.java:836)
    at quicksort.test.generateSorted(test.java:33)
    at quicksort.test.main(test.java:17)
Java Result: 1


public static int[] generateSorted(final int length, final int minVal, final int maxVal)
{
    ArrayList<Integer> data = new ArrayList<>(length);
    data.add(getRandomVal(minVal, maxVal));
    ListIterator<Integer> itr = data.listIterator();
    boolean added;
    for(int i = 0; i < length; i++)
    {
        added = false;
        int rndNum = getRandomVal(minVal, maxVal);
        while(itr.hasNext() && !added)
        {

            System.out.println(rndNum);
            Integer currentNum = itr.next();
            if(currentNum >= rndNum)
            {
                itr.add(rndNum);
                added = true;
            }
        }

        if(!added)//add to end of arrayList
            data.add(rndNum);
    }

    return data.stream().mapToInt(i -> i).toArray();
}

How can it be a concurrent modification when everything in the project is single threaded? If an itterator can't add

As an aside, what's the difference between new ArrayList<>(size) and new ArrayList(size)? Netbeans gives me a warning with the second but still compiles fine.

EDIT: oops typo, I also meant to ask what the difference is with ArrayList(size)

The exception is due to you modifying the List while still using an Iterator. Iterators need to maintain state between calls to keep track of where it is. If you modify the underlying List, the Iterator's state becomes invalid, and it can no longer guarantee correct operation. This means you can not use any methods that modify a List, while you are currently using an Iterator. You can still modify the List through an Iterator because the Iterator can now maintain it's internal state and guarantee correct operation on later calls to the iterator.

There are a couple of solutions to your problem. The first is to recreate the iterator every time you you edit the underlying list. You should be doing this anyways as it appears you are trying to keep the list sorted and if you don't start at the beginning you won't have a good sort. The second solution is to add all the numbers into the list and then sort it using something like Collections.sort

Solution 1:

List< Integer > list = new ArrayList<>();
for( int i = 0; i < length; i++ ) {
    Iterator< Integer > itr = list.listIterator();
    // Generate and add number to list
}

Solution 2:

List< Integer > list = new ArrayList<>();
for( int i = 0; i < length; i++ ) {
    int num = ...; // Generate number
    list.add( num );
}
Collections.sort( list );

The warning is because you are not providing generic arguments to a generic class. It goes away when you add the '<>' because that tells the compiler to infer the generic arguments. It was recently added to reduce the amount of code required to create something like this.

List< Map< String, Map< String, List< String > > > > list1 = new ArrayList< Map< String, Map< String, List< String > > > >();
// Becomes
List< Map< String, Map< String, List< String > > > > list2 = new ArrayList<>();

ConcurrentModificationException is thrown when collection that is being iterated using iterator is modified during the iteration not via the iterator.

This is exactly what you do in line:

data.add(rndNum);

when you access the list directly. Use itr.add() instead as you did in previous fragment of your code sample.

Your data.add(rndNum); is adding directly to your ArrayList without using the ListIterator . That causes the iterator to throw ConcurrentModificationException when it notices that the list has changed.

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