集合循环删除元素的报错
抛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());
}
}