java.util.ConcurrentModificationException原因及解决
上一篇 /
下一篇 2011-12-23 16:29:34
/ 个人分类:开发知识
java.util.ConcurrentModificationException解决办法
HashMap<String,String> map=new HashMap<String,String>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
System.out.println(map.size());
Iterator<Entry<String, String>> it = map.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String,String> entry = it.next();
String key=(String)entry.getKey();
if(key.equals("key3"))
map.remove(key); (用这句话就出错)
//it.remove();(用这句话不会出错)
System.out.println(key);
}
(这个是从网上找的)网 上查找的关于Iterator的工作机制。Iterator是工作在一个独立的线程中,并且拥有一个 mutex锁,就是说Iterator在工作的时候,是不允许被迭代的对象被改变的。Iterator被创建的时候,建立了一个内存索引表(单链表),这 个索引表指向原来的对象,当原来的对象数量改变的时候,这个索引表的内容没有同步改变,所以当索引指针往下移动的时候,便找不到要迭代的对象,于是产生错 误。List、Set等是动态的,可变对象数量的数据结构,但是Iterator则是单向不可变,只能顺序读取,不能逆序操作的数据结构,当 Iterator指向的原始数据发生变化时,Iterator自己就迷失了方向。
下面代码来自源码util的HashMap.java
hashmap进行remove的源码:
public V remove(Object key) {
Entry<K,V> e = removeEntryForKey(key);
return (e == null ? null : e.value);
}
/**
* Removes and returns the entry associated with the specified key
* in the HashMap. Returns null if the HashMap contains no mapping
* for this key.
*/
final Entry<K,V> removeEntryForKey(Object key) {
int hash = (key == null) ? 0 : hash(key.hashCode());
int i = indexFor(hash, table.length);
Entry<K,V> prev = table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
modCount++;
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
return e;
}
prev = e;
e = next;
}
return e;
}
private abstract class HashIterator<E> implements Iterator<E> :这个里面
final Entry<K,V> nextEntry() {
if (modCount != expectedModCount) 如果刚刚执行了map.remove(key),那么modcount就变了,导致iterator再进行判断的时候两个值不一样,抛出这个异常。
throw new ConcurrentModificationException();
Entry<K,V> e = next;
if (e == null)
throw new NoSuchElementException();
if ((next = e.next) == null) {
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
current = e;
return e;
}
那么执行it.remove呢:
public void remove() {
if (current == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Object k = current.key;
current = null;
HashMap.this.removeEntryForKey(k);
expectedModCount = modCount; //会执行这步,让两个值同步一下,就不会抛那个异常
}
收藏
举报
TAG: