删除ArrayList时的Java ConcurrentModificationException
当ArrayList的大小为2时,我们使用foreach循环执行删除操作,它打印最后一个元素,不会引发异常 例如:删除ArrayList时的Java ConcurrentModificationException,java,concurrency,Java,Concurrency,当ArrayList的大小为2时,我们使用foreach循环执行删除操作,它打印最后一个元素,不会引发异常 例如: ArrayList<String> a= new ArrayList<String>(Arrays.asList("abc","xyz")); for(String i : a){ a.remove(i); } // a contains "xyz" arraylista=新的ArrayList(Arrays.asList(
ArrayList<String> a= new ArrayList<String>(Arrays.asList("abc","xyz"));
for(String i : a){
a.remove(i);
}
// a contains "xyz"
arraylista=新的ArrayList(Arrays.asList(“abc”、“xyz”);
用于(字符串i:a){
a、 删除(i);
}
//a包含“xyz”
但是当我们将arrayList的大小增加到2以上,并执行该操作时,它会显示concurrentModificationException。
为什么它会显示这样的行为(它适用于2个元素,但不能超过2个)?这是实现的一个怪癖 该异常仅在尽力而为的基础上抛出,不能保证它会被抛出 要了解原因,您需要了解增强for循环的设计方式:
for (String i : a) {
a.remove(i);
}
被编译为类似于:
Iterator<String> it = a.iterator();
while (it.hasNext()) {
String i = a.next();
a.remove(i);
}
int idx = 0;
boolean hasNext() {
return idx < a.size();
}
Object next() {
checkForModification(); // throws exception if list has been modified.
return a.get(idx++);
}
Iterator it=a.Iterator();
while(it.hasNext()){
字符串i=a.next();
a、 删除(i);
}
接下来,迭代器的实现方式如下:
Iterator<String> it = a.iterator();
while (it.hasNext()) {
String i = a.next();
a.remove(i);
}
int idx = 0;
boolean hasNext() {
return idx < a.size();
}
Object next() {
checkForModification(); // throws exception if list has been modified.
return a.get(idx++);
}
intidx=0;
布尔hasNext(){
返回idx
因此,如果列表最初的大小为2,则循环的执行如下:
- 检查
:hasNext()
,并且idx==0
为true,因此返回true0<2
- 调用
:检索next()
,递增i=a.get(0)
,因此idx
idx==1
- 从
中删除a
。现在i
a.size()==1
- 检查
:hasNext()
,并且idx==1
为false,因此返回false1<1
ConcurrentModificationException
。列表仍然包含初始的第二项
如果列表最初大于2,循环将再次执行(因为
idx==1
,并且size()==initial size()-1
,所以idx
),所以next()
将在remove()
之后再次调用。列表已被修改,因此checkForModification()
引发异常。这是实现的一个怪癖
该异常仅在尽力而为的基础上抛出,不能保证它会被抛出
要了解原因,您需要了解增强for循环的设计方式:
for (String i : a) {
a.remove(i);
}
被编译为类似于:
Iterator<String> it = a.iterator();
while (it.hasNext()) {
String i = a.next();
a.remove(i);
}
int idx = 0;
boolean hasNext() {
return idx < a.size();
}
Object next() {
checkForModification(); // throws exception if list has been modified.
return a.get(idx++);
}
Iterator it=a.Iterator();
while(it.hasNext()){
字符串i=a.next();
a、 删除(i);
}
接下来,迭代器的实现方式如下:
Iterator<String> it = a.iterator();
while (it.hasNext()) {
String i = a.next();
a.remove(i);
}
int idx = 0;
boolean hasNext() {
return idx < a.size();
}
Object next() {
checkForModification(); // throws exception if list has been modified.
return a.get(idx++);
}
intidx=0;
布尔hasNext(){
返回idx
因此,如果列表最初的大小为2,则循环的执行如下:
- 检查
:hasNext()
,并且idx==0
为true,因此返回true0<2
- 调用
:检索next()
,递增i=a.get(0)
,因此idx
idx==1
- 从
中删除a
。现在i
a.size()==1
- 检查
:hasNext()
,并且idx==1
为false,因此返回false1<1
ConcurrentModificationException
。列表仍然包含初始的第二项
如果列表最初大于2,循环将再次执行(因为
idx==1
,并且size()==initial size()-1
,所以idx
),所以next()
将在remove()
之后再次调用。列表已被修改,因此checkForModification()
引发异常。在迭代列表时不能从列表中删除项目。改用迭代器。
看那边:
迭代列表时,无法从列表中删除项目。改用迭代器。 看那边:
ArrayList不是线程安全的,当您更改它的结构并进行迭代时,可能会遇到这种类型的问题 在对集合进行迭代时,需要使用迭代器安全地从集合中删除
ArrayList<String> a= new ArrayList<String>(Arrays.asList("abc","xyz"));
for (Iterator<String> iterator = a.iterator(); iterator.hasNext();) {
String string = iterator.next(); // pick one element
// do some stuffs with the content
iterator.remove(); // remove element
}
arraylista=新的ArrayList(Arrays.asList(“abc”、“xyz”);
for(Iterator Iterator=a.Iterator();Iterator.hasNext();){
String String=iterator.next();//选择一个元素
//对内容做一些处理
迭代器.remove();//删除元素
}
ArrayList不是线程安全的,当您更改它的结构并进行迭代时,可能会遇到此类问题
在对集合进行迭代时,需要使用迭代器安全地从集合中删除
ArrayList<String> a= new ArrayList<String>(Arrays.asList("abc","xyz"));
for (Iterator<String> iterator = a.iterator(); iterator.hasNext();) {
String string = iterator.next(); // pick one element
// do some stuffs with the content
iterator.remove(); // remove element
}
arraylista=新的ArrayList(Arrays.asList(“abc”、“xyz”);
for(Iterator Iterator=a.Iterator();Iterator.hasNext();){
String String=iterator.next();//选择一个元素
//对内容做一些处理
迭代器.remove();//删除元素
}
您看到这个了吗?你看到这个了吗?在这种情况下,迭代和修改发生在同一个线程上——这与线程安全无关。此外,这并不能真正回答OP的问题,即为什么在2个元素之后抛出异常。@Vasan“当您更改它的结构并进行迭代时,您可能会遇到这种类型的问题”。此外,他并没有真正问为什么它发生在2个或更多的元素上。他问自己是否有异常行为(简短的回答是否)。在这种情况下,迭代和修改发生在同一个线程上——这与线程安全无关。此外,这并不能真正回答OP的问题,即为什么在2个元素之后抛出异常。@Vasan“当您