java.util.ConcurrentModificationException 异常解决办法及原理(顶)
来源:互联网 发布:捕鱼源码有哪些权限 编辑:程序博客网 时间:2024/04/30 04:31
最近在修程序的bug,发现后台抛出以下异常:
Exception in thread "main" java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) at java.util.HashMap$KeyIterator.next(HashMap.java:828) at com.keyman.demo.test.ClearResultTable.method2(ClearResultTable.java:54) at com.keyman.demo.test.ClearResultTable.main(ClearResultTable.java:88)
找到报错行:at com.keyman.demo.test.ClearResultTable.method2(ClearResultTable.java:54)发现,报错位置:for (String s1 : sets)
Set<String> sets = map.keySet(); for (String s1 : sets) { String value = map.get(s1); // 删除满足value以abc开头的键值对 if (value.startsWith("abc")) { map.remove(s1); } }
或者下面的方式同样也会抛出异常
Iterator<String> iterator = map.keySet().iterator(); while (iterator.hasNext()) { String key = iterator.next(); String value = map.get(key); // 删除满足value以abc开头的键值对 if (value.startsWith("abc")) { map.remove(key); //iterator.remove(); // 同步modCount和expectedModCount } }
其实不管是
Map 还是 Set
这样操作时均会抛出此异常!解决办法为:如果不是Iterator迭代方式,则修改map迭代方式为Iterator()方式,采用iterator.remove();而不直接通过map.remove();
Iterator<String> iterator = map.keySet().iterator(); while (iterator.hasNext()) { String key = iterator.next(); String value = map.get(key); // 删除满足value以abc开头的键值对 if (value.startsWith("abc")) { //map.remove(value); iterator.remove(); // 关键代码,同步modCount和expectedModCount } }
详细原因如下:
发现这个位置应该是不会报错的,查找前后文,发现最有可能报错的应该是for循环里面,但是咋一看压根没错!通过查找资料发现:当修改的个数跟期望修改的个数不相等时抛出此异常。
private abstract class HashIterator<E> implements Iterator<E> { Entry<K, V> next; // next entry to return int expectedModCount; // For fast-fail int index; // current slot Entry<K, V> current; // current entry ... final Entry<K, V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); // 抛出异常 Entry<K, V> e = current = next; if (e == null) throw new NoSuchElementException(); if ((next = e.next) == null) { Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } return e; } ...}
于是查看HashMap.remove()方法代码如下:
/** * Removes the mapping for the specified key from this map if present. * * @param key key whose mapping is to be removed from the map * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) */ 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; }
你会发现,其中有modCount++操作。
modCount表示修改的次数,而并没有改变其exceptedmodCount;
接下来看看iterator.remove()方法:(java.util.Hashtable.Enumerator.remove())
public void remove() { if (!iterator) throw new UnsupportedOperationException(); if (lastReturned == null) throw new IllegalStateException("Hashtable Enumerator"); if (modCount != expectedModCount) throw new ConcurrentModificationException(); synchronized(Hashtable.this) { Entry[] tab = Hashtable.this.table; int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length; for (Entry<K,V> e = tab[index], prev = null; e != null; prev = e, e = e.next) { if (e == lastReturned) { modCount++; expectedModCount++; if (prev == null) tab[index] = e.next; else prev.next = e.next; count--; lastReturned = null; return; } } throw new ConcurrentModificationException(); } } }
而此删除元素的方法,将modCount自增的同时将exceptedModCount同样自增。也就不会抛出异常。
转载于:http://www.tuicool.com/articles/MbyMra
0 0
- java.util.ConcurrentModificationException 异常解决办法及原理(顶)
- java.util.ConcurrentModificationException 异常解决办法及原理
- java.util.ConcurrentModificationException 解决办法(使用迭代器时出现异常)
- java.util.ConcurrentModificationException异常的解决办法
- 主题:java.util.ConcurrentModificationException 异常解决办法
- 【ConcurrentModificationException】java.util.ConcurrentModificationException 解决办法
- java.util.ConcurrentModificationException异常及解决方案
- java.util.ConcurrentModificationException异常分析及处理
- java.util.ConcurrentModificationException产生原因及解决办法
- 异常:java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException异常
- java.util.ConcurrentModificationException 异常
- 异常:java.util.ConcurrentModificationException
- 异常:java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException 异常
- java.util.ConcurrentModificationException 异常
- java.util.ConcurrentModificationException异常
- HTML, 超文本标记语言, 描述网页结构
- html5动画基础(canvas,闹钟)
- gcc中编译包含math.h的程序注意加-lm参数!
- 2014 蓝桥杯 预赛 c/c++ 本科B组 第7题:六角填数(12')
- switch……case不能匹配字符串的方法
- java.util.ConcurrentModificationException 异常解决办法及原理(顶)
- Android studio、idea中svn不停输入用户密码
- python unittest
- iOS OC声明变量在@interface括号中与使用@property的区别
- java定时调度
- 常规游戏项目开发流程
- 将数组循环右移k位
- 利用Fiddler抓取安卓APP网络请求包
- RSA应用JS+PHP篇