1. 请使用List的迭代器一边遍历一边删除List中的数据,而不是直接list.remove()来一边遍历一边删除
/*
* 题目: 从集合A中删除集合B中的元素
* 会出现哪些问题:
* 1. 如果集合中存放的数据类型为int,又因为list.remove()的时候可以传入索引值,也可以传入具体数值;
* 那么这样一来,怎么删除指定值
* 解决办法: 只能通过循环遍历原集合,找到待删除的数,然后进行删除???
* 2. 如果直接边循环遍历边删除集合中的元素的时候,可能会报错: java.util.ConcurrentModificationException
* 解决办法: 使用迭代器的方式一边循环遍历集合,一边删除集合中的元素,才不会报错
* */
@Test
void test11(){
List<Integer> listA = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
listA.add(i);
}
System.out.println("listA= " + listA);
List<Integer> listB = new ArrayList<>();
for (int j = 1; j < 10; j+=2) {
listB.add(j);
}
System.out.println("listB= " + listB);
/*
//如果直接从list中边循环边删除,会报错: java.util.ConcurrentModificationException
for (Integer a : listA) {
for (Integer b : listB) {
if (a.equals(b)){
listA.remove(a);
break;
}
}
}*/
//使用迭代器的方式一边循环遍历集合,一边删除集合中的元素,才不会报错
Iterator<Integer> iterator = listA.iterator();
while (iterator.hasNext()){
Integer a = iterator.next();
for (Integer b : listB) {
if (a.equals(b)){
iterator.remove();
break;
}
}
}
System.out.println("listA-listB= " + listA);
}
2. 请使用Map的迭代器一边遍历一边删除List中的数据,而不是直接list.remove()来一边遍历一边删除
//集合循环删除的时候报错: java.util.ConcurrentModificationException
@Test
void test12(){
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("name", "Sophie");
hashMap.put("age", 20);
/*
* HashMap 中使用hashMap.remove(key)方法时,modCount != expectedModCount时,报错 java.util.ConcurrentModificationException
public V remove(Object key) {
Entry<K,V> e = removeEntryForKey(key);
return (e == null ? null : e.value);
}
*
HashMap中使用iterator.remove()方法时,
public void remove() {
if (current == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Object k = current.key;
current = null;
HashMap.this.removeEntryForKey(k);
expectedModCount = modCount;
}
*
*
* 变量 transient int modCount 的作用: 代表修改次数,即put、remove的次数
* */
System.out.println(hashMap);//{name=Sophie, age=20}
Iterator<String> iterator = hashMap.keySet().iterator();
while (iterator.hasNext()){
String key = iterator.next();
if (key.equals("name")){
//hashMap.remove(key);//key会从hashMap中被删除,会报错 java.util.ConcurrentModificationException
iterator.remove(); //快速失败的容错机制
}
}
System.out.println(hashMap);//{age=20}
}
3. 要想知道底层原理,看看源码,主要关注modCount变量
HashMap 中使用hashMap.remove(key)方法时
HashMap 中使用hashMap.remove(key)方法时,modCount != expectedModCount时,报错 java.util.ConcurrentModificationException
public V remove(Object key) {
Entry<K,V> e = removeEntryForKey(key);
return (e == null ? null : e.value);
}
HashMap中使用iterator.remove()方法时
HashMap中使用iterator.remove()方法时,
public void remove() {
if (current == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Object k = current.key;
current = null;
HashMap.this.removeEntryForKey(k);
expectedModCount = modCount;
}