集合的并发修改异常问题
指代从集合中一边遍历一边删除的时候可能会引发异常
-
可能引发问题的遍历方式
- 迭代器遍历集合且直接用集合删除元素的时候可能出现
- 增强for循环遍历集合且直接用集合删除元素的时候可能出现
package com.java.list; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ListExceptionTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Java"); list.add("Java"); list.add("MySQL"); list.add("MySQL"); System.out.println(list); // 1. 迭代器遍历删除 Iterator<String> it = list.iterator(); while (it.hasNext()) { String ele = it.next(); if ("Java".equals(ele)) { // list.remove("Java"); // 不要使用list.remove()删除元素,因为它会跳过首个元素 it.remove(); // 删除当前所在元素,并且不会向后移动 } } System.out.println(list); // 2. foreach遍历删除 for (String s : list) { String ele = it.next(); if ("Java".equals(ele)) { // list.remove("Java"); // 并发修改异常,边遍历边删除,使得删除的时候已经不存在元素了 it.remove(); // 同上,必须使用迭代器对象遍历删除 } } // 3. Lambda表达式就是执行了foreach,所以也会导致异常,必须使用迭代器对象 // 4. for循环 虽然不会出现异常错误,但是数据删除出现问题,会漏删 // 解决方案:倒着删除 } }
迭代器遍历集合,用迭代器自己的删除方法可以解决
-
使用for循环遍历并删除元素不会出现这个问题(两种解决方案)
package com.java.list; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ListExceptionTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Java"); list.add("Java"); list.add("MySQL"); list.add("MySQL"); System.out.println(list); // 1. 迭代器遍历删除 Iterator<String> it = list.iterator(); while (it.hasNext()) { String ele = it.next(); if ("Java".equals(ele)) { // list.remove("Java"); // 不要使用list.remove()删除元素,因为它会跳过首个元素 it.remove(); // 删除当前所在元素,并且不会向后移动 } } System.out.println(list); // 2. foreach遍历删除 for (String s : list) { String ele = it.next(); if ("Java".equals(ele)) { // list.remove("Java"); // 并发修改异常,边遍历边删除,使得删除的时候已经不存在元素了 it.remove(); // 同上,必须使用迭代器对象遍历删除 } } // 3. Lambda表达式就是执行了foreach,所以也会导致异常,必须使用迭代器对象 // 4. for循环 虽然不会出现异常错误,但是数据删除出现问题,会漏删 // 解决方案1:倒着删除 // 解决方案2:每次迭代器移位时对i-1 /* for (int i = 0; i < list.size(); i++) { String ele = list.get(i); if ("Java".equals(ele)) { list.remove("Java"); } }*/ // 解决方案1 for (int i = list.size() - 1; i >= 0; i--) { String ele = list.get(i); if ("Java".equals(ele)) { list.remove("Java"); } } // 解决方案2 for (int i = 0; i < list.size(); i++) { String ele = list.get(i); if ("Java".equals(ele)) { list.remove("Java"); i--; // 使得又回到0号位置,然后++继续完成后续操作 } } } }