ArrayList的遍历实现

在了解ArrayList的遍历之前,先来了解一下for是如何循环一个Iterable对象的。


ArrayList的遍历实现_第1张图片
for循环的内部原理

并发修改异常

public static void main(String[] args) {
    List list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    for (Integer t : list) {
        if (t.equals(3)) {
            list.remove(t);
        }
    }
}

执行上面的代码,会抛出ConcurrentModificationException异常:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
    at java.util.ArrayList$Itr.next(ArrayList.java:851)
....

为什么会产生并发修改异常?

要从ArrayList的实现追踪,List 的remove方法最终会调用 fastRemove,以下是fastRemove的实现:


ArrayList的遍历实现_第2张图片
fastRemove

可以看到方法中会对modCount进行++操作,modCount值改变了会带来什么后果呢?
因为是在遍历,因此最终会取集合类的下一条记录,针对List 会调用next()方法。

ArrayList的遍历实现_第3张图片
next

再跟到checkForComodification()里:

ArrayList的遍历实现_第4张图片
checkForComodification

原来在这,遍历的过程中并没有改变expectedModCount,而改变了modCount,故会抛出并发修改异常。

删除倒数第二个元素

如果把上面的代码改成下面这样:

public static void main(String[] args) {
    List list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    for (Integer t : list) {
        if (t.equals(2)) {
            list.remove(t);
        }
    }
}

程序竟然没有抛ConcurrentModificationException,正常结束了,为什么?
原来在每次取下一个元素之前,会先调用hasNext方法,判断是否还要继续遍历,如果为false就不循环了。

ArrayList的遍历实现_第5张图片
fastRemove
ArrayList的遍历实现_第6张图片
hasNext

因为删除2的时候,会更新size为2。在下一次循环的时候,cursor = 2,size = 2,就结束循环了。

你可能感兴趣的:(ArrayList的遍历实现)