今天在遍历一个Map时,需要删除Map中的某些元素,但出现了ConcurrentModificationException,上网查了下,原来是迭代器Iterator的问题。
下面用代码具体说明下:
代码的要求就是删除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。