Java ArrayList 的 ConcurrentModificationException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3184883/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ConcurrentModificationException for ArrayList
提问by mabuzer
I have the following piece of code:
我有以下一段代码:
private String toString(List<DrugStrength> aDrugStrengthList) {
StringBuilder str = new StringBuilder();
for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
aDrugStrengthList.remove(aDrugStrength);
}
}
str.append(aDrugStrengthList);
if (str.indexOf("]") != -1) {
str.insert(str.lastIndexOf("]"), "\n " );
}
return str.toString();
}
When I try to run it, I get ConcurrentModificationException
, can anyone explain why it happens, even if the code is running in same thread? And how could I avoid it?
当我尝试运行它时,我得到ConcurrentModificationException
,即使代码在同一线程中运行,谁能解释为什么会发生?我怎么能避免呢?
采纳答案by Konrad Garus
You can't remove from list if you're browsing it with "for each" loop. You can use Iterator
. Replace:
如果您使用“for each”循环浏览列表,则无法从列表中删除。您可以使用Iterator
. 代替:
for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
aDrugStrengthList.remove(aDrugStrength);
}
}
With:
和:
for (Iterator<DrugStrength> it = aDrugStrengthList.iterator(); it.hasNext(); ) {
DrugStrength aDrugStrength = it.next();
if (!aDrugStrength.isValidDrugDescription()) {
it.remove();
}
}
回答by bragboy
While iterating through the loop, you are trying to change the List value in the remove() operation. This will result in ConcurrentModificationException.
在迭代循环时,您试图更改 remove() 操作中的 List 值。这将导致 ConcurrentModificationException。
Follow the below code, which will achieve what you want and yet will not throw any exceptions
按照下面的代码,这将实现你想要的,但不会抛出任何异常
private String toString(List aDrugStrengthList) {
StringBuilder str = new StringBuilder();
List removalList = new ArrayList();
for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
removalList.add(aDrugStrength);
}
}
aDrugStrengthList.removeAll(removalList);
str.append(aDrugStrengthList);
if (str.indexOf("]") != -1) {
str.insert(str.lastIndexOf("]"), "\n " );
}
return str.toString();
}
回答by Edward Dale
Like the other answers say, you can't remove an item from a collection you're iterating over. You can get around this by explicitly using an Iterator
and removing the item there.
就像其他答案所说的那样,您无法从正在迭代的集合中删除项目。您可以通过显式使用 anIterator
并在那里删除项目来解决此问题。
Iterator<Item> iter = list.iterator();
while(iter.hasNext()) {
Item blah = iter.next();
if(...) {
iter.remove(); // Removes the 'current' item
}
}
回答by idiotgenius
there should has a concurrent implemention of List interface supporting such operation.
应该有支持这种操作的 List 接口的并发实现。
try java.util.concurrent.CopyOnWriteArrayList.class
试试 java.util.concurrent.CopyOnWriteArrayList.class
回答by froman
I like a reverse order for loop such as:
我喜欢循环的相反顺序,例如:
int size = list.size();
for (int i = size - 1; i >= 0; i--) {
if(remove){
list.remove(i);
}
}
because it doesn't require learning any new data structures or classes.
因为它不需要学习任何新的数据结构或类。
回答by Suganthan Madhavan Pillai
We can use concurrent collection classes to avoid ConcurrentModificationException while iterating over a collection, for example CopyOnWriteArrayList instead of ArrayList.
我们可以在迭代集合时使用并发集合类来避免 ConcurrentModificationException,例如 CopyOnWriteArrayList 而不是 ArrayList。
Check this post for ConcurrentHashMap
检查这篇文章以获取 ConcurrentHashMap
http://www.journaldev.com/122/hashmap-vs-concurrenthashmap-%E2%80%93-example-and-exploring-iterator
http://www.journaldev.com/122/hashmap-vs-concurrenthashmap-%E2%80%93-example-and-exploring-iterator