关于java进行迭代时更改迭代集合的问题

关于

在这次实验中遇到了一个在迭代器中remove时候的bug,注意到老师上课讲过,今天自己用代码测试了一下,果然有问题。

问题描述

如果直接利用foreach迭代,在迭代过程中,如果在迭代的集合上进行更改,例如remove,add等方法,编译时就会报错

例如,写一个ArrayList的代码如下:

List<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(4);
        list.add(6);
        list.add(8);
        list.add(9);
        list.add(10);
        for (Integer integer : list) {
            //这段代码错误. 迭代器移除会报错.
            if (integer % 2 == 0) {
                list.remove(integer);
            }
        }
        System.out.println(list);

编译时,会报如下错误:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at testForIterator.testForArray.main(testForArray.java:***)

我尝试了一下利用存储下标的方式进行更改,先将要移除的元素下标存起来,然后再移除:

List<Integer> list = new ArrayList<>();
        List<Integer> indexArray = new ArrayList<>();
        int index = 0;

        list.add(3);
        list.add(4);
        list.add(6);
        list.add(8);
        list.add(9);
        list.add(10);

        /*
         * 输出[4,6,8,9,10]与预期不同.
         * */
        for (Integer integer : list) {
            if (integer %2 == 0) {
                indexArray.add(index);
            }
            index++;
        }
        for(Integer i : indexArray) {
            list.remove(i);
        }
        System.out.println(list);

然而再移除时,依然犯了上面的错误,当然也可以一个一个移除,不过如果数据量相当大,那样效率太低,代码也会相当糟糕,因此不建议使用这种方法。

解决方法

最好的解决方法就是使用迭代器自己的remove方法,代码如下所示:

List<Integer> list = new ArrayList<>();

        list.add(3);
        list.add(4);
        list.add(6);
        list.add(8);
        list.add(9);
        list.add(10);

        /*
         * 使用迭代器本身的remove方法.
         * */
        Iterator<Integer> iter = list.iterator();
        while (iter.hasNext()) {
            int i = iter.next();
            if (i % 2 == 0) {
                iter.remove();
            }
        }
        System.out.println(list);

为什么呢?
在foreach循环中,编译器会使.next()方法在删除元素之后被调用,因此就会抛出一个ConcurrentModificationException异常。

结论

在java的集合列表中,迭代时需要增加或删除元素时,最安全的方式便是使用Iterator方法。

猜你喜欢

转载自blog.csdn.net/seriousplus/article/details/79631649