`
leonzhx
  • 浏览: 770634 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

遍历中删除容器中元素出现ConcurrentModificationException原因及处置

    博客分类:
  • Java
 
阅读更多

今天在遍历一个Map时,需要删除Map中的某些元素,但出现了ConcurrentModificationException,上网查了下,原来是迭代器Iterator的问题。

下面用代码具体说明下:

 

import java.util.HashMap;  
import java.util.Iterator;  
import java.util.Map;  
import java.util.Set;  
 
 
public class MapDeleteTest {  
    public static void main(String[] args) {  
        Map<Integer,String> m = new HashMap<Integer,String>();  
        //往map中加入测试数据  
        for(int i=1;i<6;i++) {  
            m.put(i, "value" + i);  
        }  
        //对m进行遍历,并删除key为2的项  
        Set<Map.Entry<Integer,String>> entrys = m.entrySet();  
        //第一种方法  
        for(Iterator<Map.Entry<Integer,String>> i = entrys.iterator();i.hasNext();) {  
                Map.Entry<Integer,String> entry = i.next();  
                System.out.println("key=" + entry.getKey() + "   value=" + entry.getValue());  
                if(entry.getKey()==2) {  
                    m.remove(entry.getKey());  
                }  
            }  
        //第二种方法  
        for(Map.Entry<Integer,String> entry : entrys) {  
            System.out.println("key=" + entry.getKey() + "   value=" + entry.getValue());  
            if((Integer)entry.getKey()==2) {  
                m.remove(entry.getKey());  
            }  
        }  
        //第三种方法  
        for(Iterator i = entrys.iterator();i.hasNext();) {  
            Map.Entry entry = (Map.Entry)i.next();  
            System.out.println("key=" + entry.getKey() + "   value=" + entry.getValue());  
            if((Integer)entry.getKey()==2) {  
                i.remove();  
            }  
        }  
    }     
}

代码的要求就是删除Map中key为2的项。

而在三种方法中,前两种都会抛出异常,只有第三种能正常执行。

原因:

"当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行, java.util.ConcurrentModificationException 异常也将被抛出。
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭 代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。"

所以第三种方法能正常执行。

此外,如果Collection是List,那么用简单的for循环也能正常执行【for(int i=0; i<list.size();i++ )】,因为它不依赖于Iterator。

另外对于Iterator要注意的是,一次Next后,只能执行一次remove。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/MageShuai/archive/2009/10/20/4703255.aspx

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics