42.集合:集合的并发修改异常问题

集合的并发修改异常问题

  • 指代从集合中一边遍历一边删除的时候可能会引发异常

  • 可能引发问题的遍历方式

    • 迭代器遍历集合且直接用集合删除元素的时候可能出现
    • 增强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 list = new ArrayList<>();
            list.add("Java");
            list.add("Java");
            list.add("MySQL");
            list.add("MySQL");
            System.out.println(list);
    
            // 1. 迭代器遍历删除
            Iterator 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 list = new ArrayList<>();
            list.add("Java");
            list.add("Java");
            list.add("MySQL");
            list.add("MySQL");
            System.out.println(list);
    
            // 1. 迭代器遍历删除
            Iterator 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号位置,然后++继续完成后续操作
                }
            }
        }
    }
    
    

你可能感兴趣的:(42.集合:集合的并发修改异常问题)