美文网首页程序员Java 杂谈
ArrayList的遍历实现

ArrayList的遍历实现

作者: 小小浪把_Dont_know拍 | 来源:发表于2018-01-03 09:04 被阅读53次

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


for循环的内部原理

并发修改异常

public static void main(String[] args) {
    List<Integer> 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的实现:


fastRemove

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

next

再跟到checkForComodification()里:

checkForComodification

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

删除倒数第二个元素

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

public static void main(String[] args) {
    List<Integer> 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就不循环了。

fastRemove hasNext

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

相关文章

网友评论

    本文标题:ArrayList的遍历实现

    本文链接:https://www.haomeiwen.com/subject/bigcnxtx.html