• 集合框架之——迭代器并发修改异常ConcurrentModificationException


    问题:
    我有一个集合,如下,请问,我想判断里面有没有”world”这个元素,如果有,我就添加一个”javaee”元素,请写代码实现。

    使用普通迭代器出现的异常:
    ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

    产生的原因:
    迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。
    其实这个问题描述的是:普通迭代器遍历元素的时候,通过集合是不能修改元素的。

    解决:
    A:迭代器迭代元素,迭代器修改元素
       元素是跟在刚才迭代的元素后面的。
    B:集合遍历元素,集合修改元素(普通for循环进行遍历)
       元素是在最后添加的。

     1 import java.util.ArrayList;
     2 import java.util.Iterator;
     3 import java.util.List;
     4 import java.util.ListIterator;
     5 
     6 public class ListIteratorDemo2 {
     7     public static void main(String[] args) {
     8         // 创建List集合对象
     9         List list = new ArrayList();
    10         // 添加元素
    11         list.add("hello");
    12         list.add("world");
    13         list.add("java");
    14 
    15         // 普通迭代器遍历
    16         // Iterator it = list.iterator();
    17         // while (it.hasNext()) {
    18         // String s = (String) it.next();
    19         // if ("world".equals(s)) {
    20         // list.add("javaee"); //这里报错!!!!
    21         // }
    22         // }
    23 
    24         方式1:迭代器迭代元素,迭代器修改元素
    25         而Iterator迭代器却没有添加功能,所以我们使用其子接口ListIterator
    26         ListIterator lit = list.listIterator();
    27         while (lit.hasNext()) {
    28             String s = (String) lit.next();
    29             if ("world".equals(s)) {
    30                 lit.add("javaee");
    31             }
    32         }
    33 
    34         方式2:集合遍历元素,集合修改元素(普通for)
    35         for (int x = 0; x < list.size(); x++) {
    36             String s = (String) list.get(x);
    37             if ("world".equals(s)) {
    38                 list.add("javaee");
    39             }
    40         }
    41 
    42         System.out.println("list:" + list);
    43     }
    44 }

    另外,尤其值得注意的是此迭代器remove()方法的使用:从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。每次调用 next 只能调用一次此方法。如果进行迭代时用调用此方法(remove方法)之外的其他方式修改了该迭代器所指向的 collection,则迭代器的行为是不确定的。 接口设计人员在设计Iterator<T>接口的时候已经指出,在进行迭代时如果调用了除了迭代器的remove()方法修改了该迭代器所指向的collection,则会造成不确定的后果。具体出现什么后果依迭代器的具体实现而定。针对这种不确定的后果可能出现的情况,在学习ArrayList时遇到了其中一种:迭代器抛出 ConcurrentModificationException异常。具体异常情况如下代码所示:

     1 import java.util.ArrayList;
     2 import java.util.Collection;
     3 import java.util.Iterator;
     4 
     5 public class ItaratorTest {
     6 
     7     public static void main(String[] args) {
     8         Collection<String> list = new ArrayList<String>();
     9         list.add("Android");
    10         list.add("IOS");
    11         list.add("Windows Mobile");
    12 
    13         Iterator<String> iterator = list.iterator();
    14         while (iterator.hasNext()) {
    15             String lang = iterator.next();
    16             list.remove(lang);//will throw ConcurrentModificationException
    17         }
    18     }
    19 
    20 }

    此段代码在运行时会抛出ConcurrentModificationException异常,因为我们在迭代器运行期间没有用iterator的remove()方法来删除元素,而是使用ArrayList的 remove()方法改变了迭代器所指向的collection。这就违反了迭代器的设计原则,所以发生了异常。

    总结:

    • 在用迭代器Iterator遍历collection时,如果要在遍历期间修改collection,则必须通过Iterator/listIterator来实现,否则可能会发生“不确定的后果”。
  • 相关阅读:
    转:如何判断软件功能特性的依赖
    原创:运行loadtest时报错the load test results repository was created with a previous version and is not compatible
    转:使用正则表达式进行高效的测试
    6.2.1 HTTP音频播放
    6.2 网络音频
    6.1.3 控制服务中的MediaPlayer
    android开源项目和框架
    6.1.2 加上MediaPlayer的本地服务
    6.1.1 服务
    6.1 后台音频播放
  • 原文地址:https://www.cnblogs.com/FrankLei/p/6238208.html
Copyright © 2020-2023  润新知