ArrayList和JSONArray边遍历边删除到底该如何做

 更新时间:2022年12月22日 14:57:19   作者:FeelTouch Labs  
这篇文章主要介绍了ArrayList和JSONArray边遍历边删除到底该如何做,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

话题看起来有点老生了,但是加入JSONArray还是有很多新意

ArrayList

方式1:索引遍历

        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3456);
        list.add(3456);
        list.add(4);
        for(int i =0; i < list.size(); i++) {
            if(list.get(i) == 3456) {
                list.remove(i);
            }
        }
    
        System.out.println(list);

没有异常,有输出结果[1, 2, 3456, 4],显然是不对的,没有把第二个3456删除掉,问题比较明显,就是每当删除一个条目底层就会有一次数据移动,即被删除条目下一个索引数据占据了被删除条目的位置,进入到下一轮遍历时恰好跳过了原来的下一个条目,就出现了上述的错误现象。所以此种遍历方式是不正确的。

方式2:for each遍历 

        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3456);
        list.add(3456);
        list.add(4);
        /*for(int i =0; i < list.size(); i++) {
            if(list.get(i) == 3456) {
                list.remove(i);
            }
        }*/
        for(Integer i: list) {
            if(i == 3456) {
                list.remove(i);
            }
        }
        System.out.println(list);

直接报出异常了:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    at java.util.ArrayList$Itr.next(ArrayList.java:859)

所以此种方式必然不行了。

方式3:迭代器遍历

        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3456);
        list.add(3456);
        list.add(4);
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            if(iterator.next() == 3456) {
                iterator.remove();
            }
        }
        System.out.println(list);

运行结果,完全正确[1, 2, 4]。这也是最推荐的方式。

当然,除了第3种方式外,还有2种可以考虑的方式:

方式4. 不删除,而是new一个新的list的将其中符合条件的添加到新的list,其实就实现了删除,还是比较稳妥的方式。

方式5.再一种就是对方式1的改进,一旦满足条件执行了删除,就将index--,这样也是可以实现的,只是很别扭。

JSONArray

首先,通过JSONArray的源代码看下,其中与ArrayList的关联,进入JSONArray类查看remove的代码:

private final List<Object> list;
    public JSONArray() {
        this.list = new ArrayList();
    }
   
 public boolean remove(Object o) {
        return this.list.remove(o);
    }

可以看到,底层就是调用的ArrayList的remove方法,那么据此可以推断方式1,2也会各自存在同样的问题。

那么方式3是不是就完全ok了?

JSONObject o1 = new JSONObject();
        o1.put("key", 324);
 
        JSONObject o2 = new JSONObject();
        o2.put("key", 325);
 
        JSONObject o3 = new JSONObject();
        o3.put("key", 325);
 
        JSONObject o4 = new JSONObject();
        o4.put("key", 327);
 
        JSONArray ja =  new JSONArray();
        ja.add(o1);
        ja.add(o2);
        ja.add(o3);
        ja.add(o4);
 
        Iterator<Object> o = ja.iterator();
        while (o.hasNext()) {
            JSONObject jo = (JSONObject) o.next();
            if(jo.getIntValue("key") == 325) {
                //ja.remove(jo); //不要用这种方式删除,会报出ConcurrentModificationException
                o.remove(); //这种方式OK的
            }
        }
 
        System.out.println(ja);

运行结果[{"key":324},{"key":327}]是完全正确的,只是这里有一点需要注意的是尽管循环用了iterator,那么删除的时候也要用迭代器即o.remove()而不是ja.remove(jo),否则还是会有异常的。

此外,对应的方式4,5在这里也是适用的,尤其是方式4,也是不错的方案。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Maven中jar包冲突原理与解决办法

    Maven中jar包冲突原理与解决办法

    这篇文章主要介绍了Maven中jar包冲突原理与解决办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • 详解Spring Boot下使用logback 记录多个文件日志

    详解Spring Boot下使用logback 记录多个文件日志

    这篇文章主要介绍了详解Spring Boot下使用logback 记录多个文件日志,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Kotlin中使用Java数据类时引发的Bug解决方式

    Kotlin中使用Java数据类时引发的Bug解决方式

    这篇文章主要介绍了Kotlin中使用Java数据类时引发的一个Bug,本文给大家分享问题解决方式,感兴趣的朋友跟随小编一起看看吧
    2023-09-09
  • 学习JVM之java内存区域与异常

    学习JVM之java内存区域与异常

    关于JVM内存区域的知识对于初学者来说其实是很重要的,了解Java内存分配的原理,这对于以后JAVA的学习会有更深刻的理解。下面来看看详细介绍。
    2016-07-07
  • Spring boot 整合CXF开发web service示例

    Spring boot 整合CXF开发web service示例

    这篇文章主要介绍了Spring boot 整合CXF开发web service示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 自己手写Mybatis通用batchInsert问题

    自己手写Mybatis通用batchInsert问题

    这篇文章主要介绍了自己手写Mybatis通用batchInsert问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 浅析SpringBoot自动装配的实现

    浅析SpringBoot自动装配的实现

    springboot开箱即用,其实实现了自动装配,本文重点给大家介绍SpringBoot是如何做到自动装配的,感兴趣的朋友跟随小编一起看看吧
    2022-02-02
  • java启动jar包修改JVM默认内存问题

    java启动jar包修改JVM默认内存问题

    这篇文章主要介绍了java启动jar包修改JVM默认内存问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • 关于SpringBoot微服务发布与部署的三种方式

    关于SpringBoot微服务发布与部署的三种方式

    SpringBoot 框架只提供了一套基于可执行 jar 包(executable jar)格式的标准发布形式,但并没有对部署做过多的界定,而且为了简化可执行 jar 包的生成,SpringBoot 提供了相应的 Maven 项目插件,需要的朋友可以参考下
    2023-05-05
  • Spring Boot 防止接口恶意刷新和暴力请求的实现

    Spring Boot 防止接口恶意刷新和暴力请求的实现

    本文主要介绍了Spring Boot 防止接口恶意刷新和暴力请求的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06

最新评论