繁体   English   中英

将迭代器添加到arraylist的并发修改例外

[英]Concurrent modification excpetion with iterator adding to arraylist

我正在尝试使用and迭代器将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();
}

当项目中的所有内容都是单线程时,如何进行并发修改? 如果一个发射者不能添加

顺便说一句,new ArrayList <>(size)和new ArrayList(size)有什么区别? Netbeans在第二次警告我,但仍然可以正常编译。

编辑:糟糕,我也想问一下ArrayList(size)有什么区别

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

有两种解决方案来解决您的问题。 第一种是每次您编辑基础列表时都重新创建迭代器。 无论如何,您都应该这样做,因为它似乎试图使列表保持排序,并且如果您不从头开始,那么排序就不会很好。 第二种解决方案是将所有数字添加到列表中,然后使用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 );

该警告是因为您没有为通用类提供通用参数。 当您添加'<>'时,它消失了,因为它告诉编译器推断通用参数。 最近添加它是为了减少创建类似代码所需的代码量。

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

这正是您在行中所做的:

data.add(rndNum);

当您直接访问列表时。 就像在代码示例的上一片段中一样,使用itr.add()

您的data.add(rndNum); 直接添加到您的ArrayList而不使用ListIterator 当它注意到列表已更改时,这将导致迭代器引发ConcurrentModificationException

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM