标签:
下面是网上的其他解释,更能从本质上解释原因:
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
在java常用的集合框架就是list ,set ,map 。
list 可通过下标进行遍历,set,map不能通过下表进行遍历,因此对于set ,map的数据遍历时,常常采用迭代器,不过在使用迭代器移除数据时存在陷阱。
执行如下代码:
Set set = new HashSet();
set.add(1);
set.add(2);
set.add(3);
Iterator i = set.iterator();
while(i.hashNext()){
Object o = i.next();
set.remove(o);
}
执行结果会出现以下异常:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
这个问题在集合框架使用迭代器遍历数据时存在,在java5新曾的foreach遍历方式下也存在。在通过下表遍历list的过程中不存在着个问题。
如:
List list = new ArrayList();
list .add(1);
list.add(2);
list.add(3);
for(int i = 0 ; i < list.size();i++){
list.remove(list.get(i));|| list.remove(i);
}
//
或者使用iterator的remove方法
代码能够正常执行。
当然这种情况也是容易解决,实现方式就是讲遍历与移除操作分离,即在遍历的过程中,将需要移除的数据存放在另外一个集合当中,遍历结束之后,统一移除。
------------------------------------------------------------------------------------------------------
利用java迭代器Itetator遍历并删除HashMap中的元素问题
void remove()
Removes from the underlying collection the last element returned by the
iterator (optional operation). This method can be called only once per
call to next. The behavior of an iterator is unspecified if
the underlying collection is modified while the iteration is in
progress in any way other than by calling this method.
于是有下面的改进:
解决方案三:
..............................
Iterator it=hs.keySet().iterator();
while(it.hasNext())
{
String str=(String)it.next();
System.out.println(hs);
it.remove();
}
..............................
java集合中的一个移除数据陷阱(遍历集合自身并同时删除被遍历数据)
标签:
原文地址:http://www.cnblogs.com/wzhanke/p/4817780.html