美文网首页程序员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