欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

为什么for循环中删除元素会报错

程序员文章站 2022-04-15 19:00:55
有时会遇到这样的业务需要,在 for 循环中删除列表元素,比如下面的例子。 List userList = userDao.getUserList(); for(int i = 0; i < userList.size(); i++){ User user = userList.get(i); // 进行退款操作,若退款失败,从列表中删除 boolean withdraw...

有时会遇到这样的业务需要,在 for 循环中删除列表元素,比如下面的例子。


        List<User> userList = userDao.getUserList();
        for(int i = 0; i < userList.size(); i++){
            User user = userList.get(i);
            // 进行退款操作,若退款失败,从列表中删除
            boolean withdraw = true; // 此处省略业务代码
            if(withdraw){
                userList.remove(user);
            }
       }

这样的代码是不报错的,也不会抛出异常。但是当用到迭代器时,会报错。


        List<User> userList = userDao.getUserList();
        for(User user : userList){
            // 进行退款操作,若退款失败,从列表中删除
            boolean withdraw = true; // 此处省略业务代码
            if(withdraw){
                userList.remove(user);
            }
       }

for(User user : userList){} ,这样的代码,可能会抛出异常的。

这个原因是迭代器遍历时,删除未遍历的元素时,源码层面会报错。

具体原因,回头再写一篇文章详细说明。

本篇文章的重点是说 for(int i = 0; i < userList.size(); i++){} 这样不报错,当我写了个demo去验证时,出了幺蛾子。


    public static void main(String[] args) {
        String test = "1,2,3,4,5,6,7";
        List<String> testList = Arrays.asList(test.split(","));
        log.info("testList:{}",testList);
        for(int i = 0; i < testList.size(); i++){
            String temp = testList.get(i);
            if("3".equals(temp)){
                testList.remove(temp);
            }
        }
        log.info("testList:{}",testList);
    }

我知道for循环中,这样删除元素,应该是不报错的,可是demo运行报错了。

为什么for循环中删除元素会报错
然后我就开始疑惑了,为什么会这样呢? for 循环里,不可以删除么。当我改了一行代码后,以运行了一次


List<String> testList = Arrays.asList(test.split(","));
List<String> testList = new ArrayList<>(Arrays.asList(test.split(","))) ;

    public static void main(String[] args) {
        String test = "1,2,3,4,5,6,7";
        List<String> testList = new ArrayList<>(Arrays.asList(test.split(","))) ;
        log.info("testList:{}",testList);
        for(int i = 0; i < testList.size(); i++){
            String temp = testList.get(i);
            if("3".equals(temp)){
                testList.remove(temp);
            }
        }
        log.info("testList:{}",testList);
    }

这个运行结果


  testList:[1, 2, 3, 4, 5, 6, 7]
  testList:[1, 2, 4, 5, 6, 7]

Process finished with exit code 0

完美运行了,结果符合我预期,for 循环中,删除了一个元素。

我点开了,Arrays.asList 的源码,返回值就是 ArrayList


    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

我感到头大了,头大的是,现在为什么不报错了。下边这两行代码

用第一行报错,用第二行不报错, Arrays.asList 返回的就是一个ArrayList


List<String> testList = Arrays.asList(test.split(","));
List<String> testList = new ArrayList<>(Arrays.asList(test.split(","))) ;

我提醒自己,不是见鬼了,不是见鬼了,一定是我还有东西没想到。

    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

当我点击进行这个new ArrayList<>(a)时,它居然没有跳转到别的类,而是留在了当前类java.util.Arrays 中,

尼马, Arrays这个类中,有一个内部类,叫 ArrayList。此ArrayList,非彼ArrayList。

这时,我才想起来,以前看过文章,提到过 Arrays的这个内部类,今天真的没想起来。

List testList = Arrays.asList(test.split(",")); 用这个的时候,实际调用的是,Arrays这个类的内部类 ArrayList

内部类中,没有remove 这方法。

本文地址:https://blog.csdn.net/every__day/article/details/109270953