集合框架(三种循环能否删除元素)java实现

1.普通for循环的情况

package com.wangdao.generic;
import java.util.ArrayList;
public class ForEachDemo2 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("b");
        list.add("d");
        //1.普通for循环
        for(int i = 0; i < list.size(); i++){
            if("b".equals(list.get(i))){
                list.remove(i);             //通过索引删除元素
            }
        }
        System.out.println(list);
    }
}

上面这段程序的结果是[a, b, c, d],并没有把所有的b都删除,这是为什么呢?
如果把两个挨着的b注释一个,就发现所有的b被删除了,这时候可以总结一个规律,两个相同的元素挨着的时候用普通for循环只会删除一个。需要用内存图去解决这个问题。

package com.wangdao.generic;
import java.util.ArrayList;
public class ForEachDemo2 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        // list.add("b");
        list.add("c");
        list.add("b");
        list.add("d");
        //1.普通for循环
        for(int i = 0; i < list.size(); i++){
            if("b".equals(list.get(i))){
                list.remove(i);             //通过索引删除元素
            }
        }
        System.out.println(list);
    }
}

起初内存状态是这样的。索引在0的位置上
集合框架(三种循环能否删除元素)java实现
当i到1的位置时,发现"b".equals(list.get(i))这条语句成立,于是删除b元素,由于ArrayList的属性,其长度可以自己变化,所以后面的元素整体向前移动了一个位置,这时候第二个b到达索引为1的位置,但是执行完循环语句过后,就执行i++操作,就把这个元素跳过去了,去执行判断下一个元素。
集合框架(三种循环能否删除元素)java实现
这时候我们需要做的就是在循环语句中加上i减减这条语句,先把索引往前退一个位置,之后再执行i++,代码如下:

package com.wangdao.generic;
import java.util.ArrayList;
public class ForEachDemo2 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("b");
        list.add("d");
        //1.普通for循环
        for(int i = 0; i < list.size(); i++){
            if("b".equals(list.get(i))){
                list.remove(i);             //通过索引删除元素
                i--;								//如果上面条件成立,就先回撤一个索引
            }
        }
        System.out.println(list);
    }
}

2.迭代器方法

package com.wangdao.generic;
import java.util.ArrayList;
public class ForEachDemo2 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("b");
        list.add("d");
        //2.迭代器方法
        //首先获取迭代器
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            if("b".equals(it.next())){
                //list.remove("b");//ConcurrentModificationException 不能用集合的删除方法,因为在迭代过程中集合的修改会导致并发修改异常
                it.remove();
            }
        }
        /*for(Iterator<String> it = list.iterator();it.hasNext();) {       //另一种写作方法
           if ("b".equals(it.next())) {
               //list.remove("b");//ConcurrentModificationException 不能用集合的删除方法,因为在迭代过程中集合的修改会导致并发修改异常
               it.remove();
           }
       }*/
        System.out.println(list);
    }
}

3.增强for循环

package com.wangdao.generic;
import java.util.ArrayList;
public class ForEachDemo2 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("b");
        list.add("d");
       //3.增强for循环
        for(String s: list){
            if("b".equals(s)){
                list.remove("b");           //固定格式,只能用集合的删除方法,不能删除掉,会提示并发修改异常,因为底层是迭代器实现的
            }
        }
        System.out.println(list);
    }
}

综上所述:

  • 普通for循环 :可以删除,但是索引要自减
  • 迭代器:可以删除,但必须用迭代器中自身的remove方法删除,否则出现并发修改异常
  • 增强for循环:不能删除,只能遍历,因为其底层依赖的是迭代器方法