集合循环删除元素的报错

抛ConcurrentModificationException异常!

foreach 写法实际上是对的 Iterable 、hasNext 、next 方法的简写。

因此我们从List.iterator() 着手分析,跟踪 iterator() 方法,该方法返回了 Itr 迭代器对象。

找到 List 的迭代器类

通过代码我们发现 Itr 是 ArrayList 中定义的一个私有内部类,

在 next、remove方法中都会调用 checkForComodification 方法,该方法的作用是判断 modCount != expectedModCount是否相等,

如果不相等则抛出ConcurrentModificationException异常。

每次正常执行 remove 方法后,都会对执行expectedModCount = modCount 赋值,保证两个值相等!

 

那么问题基本上已经清晰了,在 foreach 循环中执行 list.remove(item);,

对 list 对象的 modCount 值进行了修改,而 list 对象的迭代器的 expectedModCount 值未进行修改,因此抛出了ConcurrentModificationException 异常。

list的remove方法删除元素后执行了modCount++,但未对expectedModCount 进行赋值

而 迭代器中 next方法首先需要检查这两个值是否相等,否则会抛出异常。

final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}

map中remove
public final void remove() {
Node<K,V> p = current;
if (p == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
current = null;
K key = p.key;
removeNode(hash(key), key, null, false, false);
expectedModCount = modCount;
}

package com.hsjry.convert.web.mvc.controller;


import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
* @Author huangyanchang
* @Date 2022/1/25 11:11
* @Version 1.0
*/
public class ListRemoveTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
list.add(String.valueOf(i));
}
getRemoveList1(list);

getRemoveList2(list);

getRemoveList3(list);

getRemoveList4(list);

getRemoveMap1();

}

private static void getRemoveMap1() {

Map<String,String> map = new HashMap<>();
for (int i = 0; i < 5; i++) {
map.put(String.valueOf(i+5), String.valueOf(i));
}

Set keySet = map.keySet();
System.out.println(keySet.toString());
Iterator iterator=keySet.iterator();
while(iterator.hasNext()) {
Object key = iterator.next();
if ("5".equals(String.valueOf(key))) {
iterator.remove();
}
Object value = map.get(key);
System.out.println(key + " " + value);
/* [5, 6, 7, 8, 9]
5 null
6 1
7 2
8 3
9 4*/
}
}

private static void getRemoveList4(List<String> list) {
//jdk1.8移除等于3的元素
list.removeIf(item -> "3".equals(item));
System.out.println("移除后的list元素:"+ list.toString());
}

private static void getRemoveList3(List<String> list) {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if ("3".equals(item)) {
iterator.remove();
}
}
System.out.println("通过迭代器移除后的list元素:"+ list.toString());
}

private static void getRemoveList2(List<String> list) {
CopyOnWriteArrayList<String> copyList = new CopyOnWriteArrayList<>(list);
//通过对象移除等于11的元素
for (String item : copyList) {
if("3".equals(item)) {
copyList.remove(item);
}
}
System.out.println("通过对象移除后的list元素:"+ copyList.toString());
}

private static void getRemoveList1(List<String> list) {
for (int i = 0; i < list.size(); i++) {
if("3".equals(list.get(i))){
list.remove(i);
i--;
}
}
System.out.println("通过i--移除后的list元素:"+ list.toString());
}
}
posted @ 2022-01-25 16:15  宁山  阅读(79)  评论(0编辑  收藏  举报