并发修改异常的行为?迭代器内部如何工作。为什么在第二种情况下不抛出异常

时间:2016-04-21 14:09:14

标签: java collections

并发修改异常的行为?迭代器内部如何为ArrayList工作。在第二种情况下不会抛出异常。以及为什么控制在第一种情况下进入循环,尽管迭代器已经涵盖了集合的所有元素。

    //Case First
    /**********Gives Concurrent Modification Exception ****/////////////
    public static void main(String[] args) {
            List<String> sampleList = createSampleList();
            int i = 0;
            for (Iterator iterator = sampleList.iterator(); iterator.hasNext();) {
                i++;
                System.out.println("Value of I "+i);
                String value = (String) iterator.next();
                if(i==sampleList.size()){
                    System.out.println("Removing element");
                sampleList.remove(value);
                }
                System.out.println(value);
            }
        }
        private static List<String> createSampleList(){
            List<String> sampleList = new ArrayList<String>();
            sampleList.add("one");
            sampleList.add("two");
            sampleList.add("three");
            sampleList.add("four");
            sampleList.add("five");
            return sampleList;
        }
/**Output**/
Value of I 1
one
Value of I 2
two
Value of I 3
three
Value of I 4
four
Value of I 5
Removing element
five
Value of I 6
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at com.collection.iterator.Test.main(Test.java:17)


/**Output**/
   //Second Case 
/**********Does not Give Concurrent Modification *******/////////////

    public static void main(String[] args) {
            List<String> sampleList = createSampleList();
            int i = 0;
            for (Iterator iterator = sampleList.iterator(); iterator.hasNext();) {
                i++;
                System.out.println("Value of I "+i);
                String value = (String) iterator.next();
                if(i==sampleList.size()-1){
                    System.out.println("Removing element");
                sampleList.remove(value);
                }
                System.out.println(value);
            }
        }
        private static List<String> createSampleList(){
            List<String> sampleList = new ArrayList<String>();
            sampleList.add("one");
            sampleList.add("two");
            sampleList.add("three");
            sampleList.add("four");
            sampleList.add("five");
            return sampleList;
        }
/**Output**/
Value of I 1
one
Value of I 2
two
Value of I 3
three
Value of I 4
Removing element
four
/**Output**/

1 个答案:

答案 0 :(得分:1)

我得到了答案。 实际上,答案在于在ArrayList中实现迭代器。

第一种情况://每个人都知道为什么它会抛出异常,因为我们正在改变除了iterator.remove方法之外的集合结构。 但问题是:虽然它已经打印了所有五个元素,但它再次进入循环并抛出异常。 下面是iterator的hasNext()方法的实现。因此它检查游标(迭代器在迭代元素时维护游标),其大小为arraylist。在第一个案例中,在达到第五个元素后,光标变为5 ,我们从arraylist 中删除了一个元素,因此大小变为4 。所以在循环中,hasnext()方法被调用后,它返回true并进入循环。

public boolean hasNext() {
    return (this.cursor != ArrayList.this.size);
}

这也解释了为什么在第二种情况下不抛出异常,因为当我们删除了第4个元素时,游标值为4,并且ArrayList大小也变为4.在这种情况下,下一个返回false并且它不会进入循环而不会next()方法实际上抛出ConcurrentModificationException。