GVKun编程网logo

使用Iterator的ConcurrentModificationException(iterator remove)

17

对于使用Iterator的ConcurrentModificationException感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解iteratorremove,并且为您提供关于-集合遍

对于使用Iterator的ConcurrentModificationException感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解iterator remove,并且为您提供关于- 集合 遍历 foreach Iterator 并发修改 ConcurrentModificationException MD、3种方式解决iterator迭代器ConcurrentModificationException、ArrayList中ConcurrentModificationException、ConcurrentModificationException的宝贵知识。

本文目录一览:

使用Iterator的ConcurrentModificationException(iterator remove)

使用Iterator的ConcurrentModificationException(iterator remove)

我使用迭代器遍历一个集合,如下所示:

Iterator<Entity> entityItr = entityList.iterator();

    while (entityItr.hasNext())
    {
        Entity curr = entityItr.next();

        for (Component c : curr.getComponents())
        {
            if (c instanceof PlayerControlled)
            {
                ((PlayerControlled) c).pollKeyboard();  
            }
        }
    }

但是在下面的行中,我得到了ConcurrentModificationException

 Entity curr = entityItr.next();

当我不进行任何更改时,为什么会发生这种情况?

非常感谢

编辑-堆栈跟踪:

java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at cw.systems.Input.checkInputs(Input.java:31)
at cw.systems.Input.begin(Input.java:21)
at cw.misc.Game.render(Game.java:73)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:207)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)

- 集合 遍历 foreach Iterator 并发修改 ConcurrentModificationException MD

- 集合 遍历 foreach Iterator 并发修改 ConcurrentModificationException MD

Markdown 版本笔记 我的 GitHub 首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目录

[TOC]

为什么不能在 foreach 循环里进行元素的 remove/add 操作

参考: Hollis 的公众号文章

背景

在阿里巴巴 Java 开发手册中,有这样一条规定:

但是手册中并没有给出具体原因,本文就来深入分析一下该规定背后的思考。

foreach 循环

foreach 循环(Foreach loop)是计算机编程语言中的一种控制流程语句,通常用来循环遍历数组或集合中的元素。

Java 语言从 JDK 1.5.0 开始引入 foreach 循环。在遍历数组、集合方面,foreach 为开发人员提供了极大的方便。通常也被称之为增强for循环

foreach 语法格式如下:

for(元素类型t 元素变量x : 遍历对象obj){ 
     引用了xjava语句; 
}

以下实例演示了 普通 for 循环 和 foreach 循环使用:

public static void main(String[] args) {
    // 使用ImmutableList初始化一个List
    List<String> userNames = ImmutableList.of("Hollis", "hollis", "HollisChuang", "H");

    System.out.println("使用for循环遍历List");
    for (int i = 0; i < userNames.size(); i++) {
        System.out.println(userNames.get(i));
    }

    System.out.println("使用foreach遍历List");
    for (String userName : userNames) {
        System.out.println(userName);
    }
}

可以看到,使用 foreach 语法遍历集合或者数组的时候,可以起到和普通 for 循环同样的效果,并且代码更加简洁。所以,foreach 循环也通常也被称为增强 for 循环。

但是,作为一个合格的程序员,我们不仅要知道什么是增强 for 循环,还需要知道增强for循环的原理是什么

其实,增强 for 循环也是 Java 给我们提供的一个语法糖,如果将以上代码编译后的 class 文件进行反编译(使用 jad 工具)的话,可以得到以下代码:

Iterator iterator = userNames.iterator();
do{
    if(!iterator.hasNext())
        break;
    String userName = (String)iterator.next();
    if(userName.equals("Hollis"))
        userNames.remove(userName);
} while(true);
System.out.println(userNames);

可以发现,原本的增强 for 循环,其实是依赖了 while 循环和 Iterator 实现的。

问题重现

规范中指出不让我们在 foreach 循环中对集合元素做 add/remove 操作,那么,我们尝试着做一下看看会发生什么问题。

首先使用双括弧语法(double-brace syntax)建立并初始化一个 List,其中包含四个字符串,分别是 Hollis、hollis、HollisChuang 和 H:

List<String> userNames = new ArrayList<String>() {{
    add("Hollis");
    add("hollis");
    add("HollisChuang");
    add("H");
}};

然后使用普通 for 循环对 List 进行遍历,删除 List 中元素内容等于 Hollis 的元素,然后输出 List:

for (int i = 0; i < userNames.size(); i++) {
    if (userNames.get(i).equals("Hollis")) {
        userNames.remove(i);
    }
}
System.out.println(userNames);

输出结果如下

[hollis, HollisChuang, H]

以上是使用普通的 for 循环在遍历的同时进行删除,那么,我们再看下,如果使用增强 for 循环的话会发生什么:

for (String userName : userNames) {
    if (userName.equals("Hollis")) {
        userNames.remove(userName);
    }
}
System.out.println(userNames);

以上代码,使用增强 for 循环遍历元素,并尝试删除其中的 Hollis 字符串元素。运行以上代码,会抛出以下异常:

java.util.ConcurrentModificationException

同样的,读者可以尝试下在增强 for 循环中使用 add 方法添加元素,结果也会同样抛出该异常。

之所以会出现这个异常,是因为触发了一个 Java 集合的错误检测机制 ——fail-fast

fail-fast

接下来,我们就来分析下在增强 for 循环中 add/remove 元素的时候会抛出 java.util.ConcurrentModificationException 的原因,即解释下到底什么是 fail-fast 进制。

fail-fast,即快速失败,它是 Java 集合的一种错误检测机制当多个线程对非fail-safe的集合类进行结构上的改变的操作时,有可能会产生fail-fast机制,这个时候就会抛出 ConcurrentModificationException(当方法检测到对象的并发修改,但不允许这种修改时就抛出该异常)。

需要注意的是,即使不是多线程环境,如果单线程违反了规则,同样也有可能会抛出改异常。

那么,在增强 for 循环进行元素删除,是如何违反了规则的呢?

要分析这个问题,我们先将增强 for 循环这个语法糖进行解糖(使用 jad 对编译后的 class 文件进行反编译),得到以下代码:

public static void main(String[] args) {
    // 使用ImmutableList初始化一个List
    List<String> userNames = new ArrayList<String>() {{
        add("Hollis");
        add("hollis");
        add("HollisChuang");
        add("H");
    }};

    Iterator iterator = userNames.iterator();
    do
    {
        if(!iterator.hasNext())
            break;
        String userName = (String)iterator.next();
        if(userName.equals("Hollis"))
            userNames.remove(userName);
    } while(true);
    System.out.println(userNames);
}

然后运行以上代码,同样会抛出异常。我们来看一下 ConcurrentModificationException 的完整堆栈:

通过异常堆栈我们可以到,异常发生的调用链 ForEachDemo 的第 23 行,Iterator.next 调用了 Iterator.checkForComodification 方法 ,而异常就是 checkForComodification 方法中抛出的。

其实,经过 debug 后,我们可以发现,如果 remove 代码没有被执行过,iterator.next 这一行是一直没报错的。抛异常的时机也正是 remove执行之后的的那一次next方法的调用

我们直接看下 checkForComodification 方法的代码,看下抛出异常的原因:

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

代码比较简单,modCount != expectedModCount 的时候,就会抛出 ConcurrentModificationException。

那么,就来看一下,remove/add 操作室如何导致 modCount 和 expectedModCount 不相等的吧。

remove/add 做了什么

首先,我们要搞清楚的是,到底 modCount 和 expectedModCount 这两个变量都是个什么东西。

通过翻源码,我们可以发现:

  • modCount 是 ArrayList 中的一个成员变量。它表示该集合实际被修改的次数。
  • expectedModCount 是 ArrayList 中的一个内部类 ——Itr 中的成员变量。expectedModCount 表示这个迭代器期望该集合被修改的次数。其值是在 ArrayList.iterator 方法被调用的时候初始化的。只有通过迭代器对集合进行操作,该值才会改变。

Itr 是一个 Iterator 的实现,使用 ArrayList.iterator 方法可以获取到的迭代器就是 Itr 类的实例。

他们之间的关系如下:

class ArrayList{
    private int modCount;
    public void add();
    public void remove();
    private class Itr implements Iterator<E> {
        int expectedModCount = modCount;
    }
    public Iterator<E> iterator() {
        return new Itr();
    }
}

其实,看到这里,大概很多人都能猜到为什么 remove/add 操作之后,会导致 expectedModCount 和 modCount 不想等了。

通过翻阅代码,我们也可以发现,remove 方法核心逻辑如下: !

可以看到,它只修改了 modCount,并没有对 expectedModCount 做任何操作。

简单总结一下,之所以会抛出 ConcurrentModificationException 异常,是因为我们的代码中使用了增强 for 循环,而在增强for循环中,集合遍历是通过iterator进行的,但是元素的add/remove却是直接使用的集合类自己的方法。这就导致 iterator 在遍历的时候,会发现有一个元素在自己不知不觉的情况下就被删除 / 添加了,就会抛出一个异常,用来提示用户,可能发生了并发修改

正确姿势

至此,我们介绍清楚了不能在 foreach 循环体中直接对集合进行 add/remove 操作的原因。

但是,很多时候,我们是有需求需要过滤集合的,比如删除其中一部分元素,那么应该如何做呢?有几种方法可供参考:

直接使用普通 for 循环进行操作

我们说不能在 foreach 中进行,但是使用普通的 for 循环还是可以的,因为普通 for 循环并没有用到 Iterator 的遍历,所以压根就没有进行 fail-fast 的检验。

for (int i = 0; i < 1; i++) {
    if (userNames.get(i).equals("Hollis")) {
        userNames.remove(i);
    }
}

直接使用 Iterator 进行操作

除了直接使用普通 for 循环以外,我们还可以直接使用 Iterator 提供的 remove 方法。

Iterator iterator = userNames.iterator();
while (iterator.hasNext()) {
    if (iterator.next().equals("Hollis")) {
        iterator.remove();
    }
}

如果直接使用 Iterator 提供的 remove 方法,那么就可以修改到 expectedModCount 的值。那么就不会再抛出异常了。其实现代码如下:

使用 Java8 中提供的 filter 过滤

Java 8 中可以把集合转换成流,对于流有一种 filter 操作, 可以对原始 Stream 进行某项测试,通过测试的元素被留下来生成一个新 Stream。

userNames = userNames.stream()
    .filter(userName -> !userName.equals("Hollis"))
    .collect(Collectors.toList());

使用 fail-safe 的集合类

在 Java 中,除了一些普通的集合类以外,还有一些采用了 fail-safe 机制的集合类,比如 ConcurrentLinkedDeque。这样的集合容器在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历

由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发 ConcurrentModificationException。

基于拷贝内容的优点是避免了 ConcurrentModificationException,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。

java.util.concurrent 包下的容器都是安全失败,可以在多线程下并发使用,并发修改。

使用增强 for 循环其实也可以

如果,我们非常确定在一个集合中,某个即将删除的元素只包含一个的话, 比如对 Set 进行操作,那么其实也是可以使用增强 for 循环的,只要在删除之后,立刻结束循环体,不要再继续进行遍历就可以了,也就是说不让代码执行到下一次的next方法

for (String userName : userNames) {
    if (userName.equals("Hollis")) {
        userNames.remove(userName);
        break;
    }
}

以上这五种方式都可以避免触发 fail-fast 机制,避免抛出异常。如果是并发场景,建议使用 concurrent 包中的容器,如果是单线程场景,Java8 之前的代码中,建议使用 Iterator 进行元素删除,Java8 及更新的版本中,可以考虑使用 Stream 及 filter。

总结

我们使用的增强 for 循环,其实是 Java 提供的语法糖,其实现原理是借助 Iterator 进行元素的遍历。

但是如果在遍历过程中,不通过 Iterator,而是通过集合类自身的方法对集合进行添加 / 删除操作。那么在 Iterator 进行下一次的遍历时,经检测发现有一次集合的修改操作并未通过自身进行,那么可能是发生了并发被其他线程执行的,这时候就会抛出异常,来提示用户可能发生了并发修改,这就是所谓的 fail-fast 机制。

当然还是有很多种方法可以解决这类问题的。比如使用普通 for 循环、使用 Iterator 进行元素删除、使用 Stream 的 filter、使用 fail-safe 的类等。

3种方式解决iterator迭代器ConcurrentModificationException

3种方式解决iterator迭代器ConcurrentModificationException

3种方式解决iterator迭代器并发修改异常ConcurrentModificationException

在使用迭代器的时候,时长会遇到 ConcurrentModificationException(并发修改异常)

这也是很多人头疼的问题

并发修改异常产生的原因

在使用迭代器迭代集合的同时,使用原集合修改元素;如果迭代器发现自己和集合不一样,就会抛出 ConcurrentModificationException 异常。

先拿出我写的小案例:

Collection<String> list = new ArrayList<>();
    list.add("JAVA");
    list.add("Python");
    list.add("PHP");
    Iterator<String> it = list.iterator();
    while(it.hasNext()) {
        if (it.next().equals("PHP")) {
            list.add("我全都要");
        }
    }

一运行,就抛异常

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    at java.util.ArrayList$Itr.next(ArrayList.java:859)
    at Test.main(Test.java:13)

看看源码:

at java.util.ArrayList$Itr.next(ArrayList.java:859)

public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)

final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }

modCount 为 ArrayList 的类成员变量,用来记录其变化次数;而 expectedModCount 作为迭代器成员变量,则存储了 iterator 初始化时记录到的 ArrayList 中的 modCount 值。如果 modConut 和 expectedModCount 不相等,则抛出 ConcurrentModificationException 异常。

解决方法

这里我使用3种解决方案

  1. 使用列表迭代器
  2. 不使用迭代器遍历,使用普通for遍历
  3. 使用toArray

第一种:使用列表迭代器

List<String> list = new ArrayList<>();
    list.add("JAVA");
    list.add("Python");
    list.add("PHP");
    ListIterator<String> it = list.listIterator();

    while(it.hasNext()){
        if (it.next().equals("PHP")) {
            // list.add("以上几个");  //这里注意:直接修改原集合会抛出并发修改异常
            it.add("我全都要");
        }
    }
    System.out.println(list);

输出结果

[JAVA,Python,PHP,我全都要]

第二种:不使用迭代器遍历,使用普通for遍历

ArrayList<String> list = new ArrayList<>();
    list.add("JAVA");
    list.add("Python");
    list.add("PHP");
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i).equals("PHP")) {
            list.remove("我全都要");
            list.add("C++");
        }
    }
    System.out.println(list);

输出结果

[JAVA,C++]

第三种:使用toArray

ArrayList<String> list = new ArrayList<>();
    list.add("JAVA");
    list.add("Python");
    list.add("PHP");
    Object[] obj = list.toArray();
    for (int i = 0; i < obj.length; i++) {
        if (obj[i].equals("PHP")) {
            list.add(0,"今晚学习");
        }
    }
    System.out.println(list);

输出结果

[今晚学习,JAVA,PHP]

通过以上3种方法都可以解决 iterator 导致的并发修改异常。

如果非要使用迭代器修改集合,可以使用列表迭代器 ListIterator

ArrayList中ConcurrentModificationException

ArrayList中ConcurrentModificationException

java中两种基本的集合结构ArrayList和LinkedList底层有两种不同的存储方式实现,ArrayList为数组实现,属于顺序存储,LinkedList为链表实现,属于链式存储,在对ArrayList做迭代删除时,会出现ConcurrentModificationException

public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("aa");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            list.remove(next);
        }
    }
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)
	at com.baicells.linked.list.ListTest.main(ListTest.java:23)

但如果在list再添加一个元素,如bb,此时list.size = 2,上述代码运行结束后,list中只有bb,虽然与预期结果不一致,但并没有出现ConcurrentModificationException,当再次向集合中添加更多元素时,又出现了ConcurrentModificationException,使用的jdk版本为1.8.

ArrayList源码中,方法iterator()返回了Itr对象

/**
     * Returns an iterator over the elements in this list in proper sequence.
     *
     * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
     *
     * @return an iterator over the elements in this list in proper sequence
     */
    public Iterator<E> iterator() {
        return new Itr();
    }

Itr为ArrayList内部类,主要关注hasNext,next,checkForComodification方法

/**
     * An optimized version of AbstractList.Itr
     */
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

modCount在add和remove时都会执行++操作,这个可在ArrayList源码中找到出处

在Ite类中,将expectedModCount 的大小初始化为modCount,当执行hashNex和nex时,都不会使modCount的值发生变化

当list中只有一个数据时,此时cursor=0,size=1,hasNex返回true,在next方法中校验modCount和expectedModCount是否相等,如果不相等,则抛出并发修改异常,如果相等,对cursor做了+1操作

final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

此时两者是相等的,都为1,然后执行remove操作删除该数据

public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

    /*
     * Private remove method that skips bounds checking and does not
     * return the value removed.
     */
    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

remove是对modCount做了++操作,并且对size做了--操作,while循环继续,hasNext,cursor=1,size=0,两者不相等,则进入到循环,执行next操作

此时modCount在上述remove操作时已经做了++操作,expectedModCount的值却没有变化,故modCount和expectedModCount是不相等的,因此抛出ConcurrentModificationException

当输入两个参数时为什么就不会报错了,虽然结果不是预期的清空了集合?

当集合为2时,在第一次删除后,各关键属性值分别为cursor=1,modCount在add两次后变为2,在remove一次后变为3,expectedModCount=2,size在remove后--,变为1,故此时在while循环hasNext中对比cursor!=size,返回false,while循环结束,继续向下走,所以最后集合中剩下了第二次add的结果,第一次add结果被删除,程序也没有出现ConcurrentModificationException异常。

当输入三个参数或者更多时,会怎样?

继续按照上述思路分析,当集合中有三个元素时,在第一次删除后,各关键属性值分别为cursor=1,modCount在add三次后变为3,在remove一次后变为4,expectedModCount=3,size在remove后--,变为2,此时while循环中cursor!=size返回true,进入while循环,next方法中检测到modCount != expectedModCount返回false,则抛出ConcurrentModificationException

当为更多元素时,在第二次进入到next方法后,都将抛出ConcurrentModificationException,只有在数组元素个数为2时,才不会发生ConcurrentModificationException,但结果也不是我们预期的

 

综上,不要在迭代集合时删除元素,即使是foreach或者普通for循环(普通for循环或者foreach也会造成size--),也不要这么做,这样做可能造成我们意想不到错误。

 

ConcurrentModificationException

ConcurrentModificationException

This is a result of concurrent iteration and modification. It is pretty
hard to define and implement what should happen if an iterated-over
collection is modified. That''s why Java''s iterators are typically
designed so that they immediately fail when the underlying collection is
modified. The JavaDoc for ArrayList, e.g., has to say the following:


The iterators returned by this class''s iterator and listIterator methods
are fail-fast: if list is structurally modified at any time after the
iterator is
created, in any way except through the iterator''s own remove or add
methods, the iterator will throw a ConcurrentModificationException.
Thus, in the
face of concurrent modification, the iterator fails quickly and cleanly,
rather than risking arbitrary, non-deterministic behavior at an
undetermined time
in the future.

撰写多线程代码时,你遇到过多少次下面的提示:
Exception in thread "main" java.util.ConcurrentModificationException 


这个异常产生的原因有几个。一是直接对集合调用删除操作而不是在枚举器上。二是不同的线程试图对集合进行增删操作的时候。

这个解决办法的第一步就是同步代码,使得你在枚举的时候其它的线程不能增删记录。但是如果每个枚举过程要进行复杂的计算或者是数据库访问的一部分的话,这个同步就会导致可怕的后果。为了减少负面影响,可以拷贝一个只读的枚举器,去掉同步,然后采用下列代码所示的方法:

 
private List list;
  public void add(Object obj) {
  synchronized(list) {
  list.add(obj);
  }
  }
  public void perform( ) {
  Iterator iterator = null;
  synchronized(list) {
  iterator = new CopiedIterator(list.iterator( ));
  }
  while(iterator.hasNext( )) {
  // perform resource or cpu hungry work
  }
  }
重要的是记住,CopiedIterator不是一个克隆,只是一个只读的拷贝,所以它并没有保持原有的全部功能。最重要的是,不能再调用CopiedIterator.remove方法了。CopiedIterator.remove的实现如下:

 
public class CopiedIterator implements Iterator {
  private Iterator iterator = null;
  public CopiedIterator(Iterator itr) {
  LinkedList list = new LinkedList( );
  while(itr.hasNext( )) {
  list.add(itr.next( ));
  }
  this.iterator = list.iterator( );
  }
  public boolean hasNext( ) {
  return this.iterator.hasNext( );
  }
  public void remove( ) {
  throw new UnsupportedOperationException("This is a read-only iterator. 
  ");
  }
  public Object next( ) {
  return this.iterator.next( );
  }
  }
枚举器的只读拷贝将用在同步状态上的时间减少到最小,因此可以增强全局的效率。

关于使用Iterator的ConcurrentModificationExceptioniterator remove的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于- 集合 遍历 foreach Iterator 并发修改 ConcurrentModificationException MD、3种方式解决iterator迭代器ConcurrentModificationException、ArrayList中ConcurrentModificationException、ConcurrentModificationException等相关知识的信息别忘了在本站进行查找喔。

本文标签: