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

标签 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**/

最佳答案

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

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

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

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

关于java - 并发修改异常的行为?迭代器内部是如何工作的。为什么在第二种情况下不会抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36772177/

相关文章:

scala - 为什么数组需要 ClassTag 而像 List 这样的集合不需要?

.net - 如何在不枚举的情况下将泛型词典转换为非泛型?

java - 我是否需要自定义 Spliterator 来避免额外的 .stream() 调用?

java - 将 Instant 从大纪元时间转换为微秒

Java 扫描器良好实践

java - 通过阈值列表对值列表进行分类

java - 如何按空格分割字符串(有异常(exception))

java - 合并排序创建内存堆

java - 解析文件并按属性对行进行排序

c# - 使用不同的泛型参数初始化泛型集合数组