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,也是不错的方案。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
详解Spring Boot 自定义PropertySourceLoader
这篇文章主要介绍了详解Spring Boot 自定义PropertySourceLoader,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2017-05-05Java中JDK14的新特性之JFR,JMC和JFR事件流(推荐)
JFR是一个基于事件的低开销的分析引擎,具有高性能的后端,可以以二进制格式编写事件,而JMC是一个GUI工具,用于检查JFR创建的数据文件。本文给大家介绍Java中JDK14的新特性之JFR,JMC和JFR事件流的相关知识,感兴趣的朋友一起看看吧2020-05-05selenium4.0版本在springboot中的使用问题的坑
本文主要介绍了selenium4.0版本在springboot中的使用问题的坑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2022-07-07利用spring-data-redis实现incr自增的操作
这篇文章主要介绍了利用spring-data-redis实现incr自增的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2020-11-11
最新评论