迭代器添加到arraylist的并发修改异常

时间:2014-08-14 17:18:52

标签: java arraylist iterator

我正在尝试使用和迭代器将一个Integer添加到数组列表中。它在第三次调用迭代器的.next()时崩溃了。这是堆栈跟踪和代码

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();
}

当项目中的所有内容都是单线程时,如何进行并发修改?如果itterator无法添加

另外,新的ArrayList&lt;&gt;(大小)和新的ArrayList(大小)之间有什么区别? Netbeans给了我第二个警告,但仍然编译好。

编辑:oops拼写错误,我也想问一下与ArrayList(大小)的区别是什么

3 个答案:

答案 0 :(得分:3)

异常是由于您在使用Iterator时修改了List。迭代器需要在调用之间保持状态以跟踪它的位置。如果修改基础列表,则迭代器的状态将变为无效,并且无法再保证正确的操作。这意味着当前使用Iterator时,不能使用任何修改List的方法。您仍然可以通过Iterator修改List,因为Iterator现在可以维护它的内部状态,并保证在以后调用迭代器时能够正确操作。

您的问题有几种解决方案。第一种是每次编辑基础列表时重新创建迭代器。你应该这样做,因为看起来你试图保持列表排序,如果你不是从头开始你就不会有好的排序。第二种解决方案是将所有数字添加到列表中,然后使用Collections.sort

之类的内容对其进行排序

解决方案1:

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

解决方案2:

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

警告是因为您没有为泛型类提供泛型参数。当你添加&#39;&lt;&gt;&#39;它会消失。因为它告诉编译器推断泛型参数。最近添加了它来减少创建这样的代码所需的代码量。

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<>();

答案 1 :(得分:1)

当迭代期间不通过迭代器修改使用迭代器迭代的集合时,抛出

ConcurrentModificationException

这正是你在行中所做的:

data.add(rndNum);

直接访问列表时。使用itr.add()代替您在代码示例的上一个片段中所做的操作。

答案 2 :(得分:1)

您的data.add(rndNum);在不使用ArrayList的情况下直接添加到ListIterator。这会导致迭代器在注意到列表已更改时抛出ConcurrentModificationException