遍历列表时出现 ConcurrentException
我现在的状态很奇特。我有一个如下所示的列表:-
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
现在,当我进行多种类型的遍历时,例如使用高级 for、迭代器和普通 for 循环,下面是示例代码片段:-
1>高级循环:-
try {
for(String a : list) {
System.out.println(a);
list.add("f");
}
} catch (Exception e) {
e.printStackTrace();
}
2>迭代器:-
try {
Iterator<String> itr = list.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
list.add("f");
}
} catch (Exception e) {
e.printStackTrace();
}
3>正常循环:-
for (int i=0;i<list.size();i++) {
System.out.println(list.get(i));
list.add("f");
}
现在,特殊的问题是,当使用高级 for 循环和迭代器时,我得到以下异常:-
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
the reason i know, that while iterating through a list, one cannot modify it parallely.
但是当我使用正常 for 循环时,它就可以正常工作,我错过了什么吗?
请帮忙!!!...
I am in a very peculiar state. I have a list something like below :-
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
Now when i do multiple type of traversing, like using advanced for, iterator, and normal for loop, below are the sample code snippets :-
1> Advanced Loop :-
try {
for(String a : list) {
System.out.println(a);
list.add("f");
}
} catch (Exception e) {
e.printStackTrace();
}
2> Iterator :-
try {
Iterator<String> itr = list.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
list.add("f");
}
} catch (Exception e) {
e.printStackTrace();
}
3> Normal Loop :-
for (int i=0;i<list.size();i++) {
System.out.println(list.get(i));
list.add("f");
}
Now, the peculiar problem is, that when using advanced for-loop and iterator, i get the following exception : -
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
the reason i know, that while iterating through a list, one cannot modify it parallely.
but when i use the normal for loop, then it works properly, Am i missing something??
Please Help!!!..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果修改 List,则会导致从它创建的任何 Iterator 对象失效。高级循环 (1) 编译为与迭代器循环 (2) 几乎相同的代码,这意味着在幕后创建了一个 Iterator 对象。
ConcurrentMOdificationException 的 javadocs 有更多详细信息。
如果您想在迭代时添加,请使用
If you modify a List, it invalidates any Iterator objects created from it. The advanced loop (1) compiles to nearly the same code as the iterator loop (2), meaning that there is an Iterator object created behind the scenes.
The javadocs for ConcurrentMOdificationException have more details.
If you want to add while iterating, use
高级循环只是迭代器的语法糖。每当运行
next()
时,迭代器总是调用checkForCommodification()
。如果此方法发现您修改了列表,它将引发异常。运行“正常循环”不提供检查修改计数的功能,因为您没有使用迭代器进行循环,而是严格使用 for 循环构造。
The advanced loop is just syntactic sugar for the iterator. The iterator always calls
checkForComodification()
whenever it runsnext()
. This method will throw an exception if it sees that you modified the list.Running the "Normal Loop" does not provide this functionality of checking the modification count because you aren't using an iterator to loop, you are strictly using the for loop construct.
对列表进行 for 循环会产生严重的问题。您将重新读取条目(删除先前的条目可能会导致此情况),并且可能会遇到 IndexOutOfBoundsExceptions。使用 CopyOnWriteArrayList 进行并发- 安全列表没有太多开销,具体取决于您的应用程序。如果您对列表有很多写入,请使用 ConcurrentLinkedQueue,但请注意,这就像一个队列,你只能用它做类似队列的事情,比如只添加到末尾并从前面删除。
Doing a for loop on the list will create serious problems. You'll get entries being re-read (deleting a previous entry might cause this) and you might get IndexOutOfBoundsExceptions. Use CopyOnWriteArrayList for a concurrent-safe list with not that much overhead, depending on your application. If you have many writes to the list, use ConcurrentLinkedQueue, but be aware that this acts like a queue and you can only do queue-like stuff with it like only adding to the end and removing from the front.
您应该记住,ConcurrentModificationException 是由 Iterator 的 next 方法引发的,而不是由 List 的 add 方法引发的。这意味着,当您在循环中添加新元素时,列表实际上会被修改。如果在添加新元素后退出循环,则不会引发异常,并且该元素会添加到列表中。
否则,您可以使用迭代器的添加和删除方法来修改循环内的列表。
You should keep in mind that the ConcurrentModificationException is thrown by the Iterator's next method, but not by the List's add method. This means, the list is actually modified when you add a new element in the loop. If you quit the loop after adding a new element, there is no exception thrown and the element is added to the list.
Otherwise you can use Iterator's add and remove method to modify the list inside the loop.
而不是直接使用列表对象。您可以使用 Iterator() 类的 add()、remove() 来解决 ArrayList() 中的此错误。
而不是使用
List; list = new ArrayList();
use
主要原因是ArrayList不是线程安全的,而CopyOnWriteArrayList是线程安全的。
java文档参考:
ArrayList - https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html
CopyOnWriteArrayList - https://docs.oracle.com/javase/7/docs/api /java/util/concurrent/CopyOnWriteArrayList.html
如果您遵循上述方法,那么所有代码片段都将起作用。
Instead of directly using the list object. you can use add(),remove() of the Iterator() class to resolve this error in ArrayList().
Instead of using
List<String> list = new ArrayList<String>();
use
The main reason is ArrayList is not thread safety whereas CopyOnWriteArrayList is thread safety.
java docs reference:
ArrayList -https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html
CopyOnWriteArrayList-https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArrayList.html
If you have follow the above approach then all the code snippets will work.