ArrayList删除元素的细则
删除ArrayList数组中某个元素,通常会使用for循环匹配目标元素完成删除操作。
public void remove(List<String> list, String str){Iterator<String> it = list.iterator();while(it.hasNext()){if(str.equals(it.next())){it.remove();} }
}
public void remove(List<String> list, String str){for(String s: list){if(str.equals(it.next())){list.remove(s);} }
}
以上两种写法,第一种使用了显示声明迭代器Iterator的方式来遍历数组,匹配成功后删除;第二种使用JDK语法糖foreach的方式来遍历数组,匹配成功后删除。但是第二种写法会发生ConcurrentModificationException异常,简单来讲foreach是一个语法糖,其在进行遍历的时候还是使用的是ArrayList内部自己实现的迭代器Iterator,foreach的每次遍历都相当于调用Iterator的next()方法获取下一个元素,且方法内部会校验Iterator维护的expectedModCount是否等于ArrayList类维护的modCount,如不等就会抛出ConcurrentModificationException异常,又因为直接通过ArrayList的remove()方法来删除元素只会维护modCount,所以最终导致expectedModCount和modCount不相等。
ArrayList#remove
抛开remove()方法中越界校验、移除后数组拷贝等逻辑,发现ArrayList在进行删除元素前会先将modCount属性自增加一来记录当前数组的修改次数。这就导致一边使用foreach语法糖遍历数组,一边使用ArrayList类remove()方法删除元素会发生ConcurrentModificationException异常。
public E remove(int index) {rangeCheck(index);modCount++;E oldValue = elementData(index);int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index,numMoved);elementData[--size] = null; // clear to let GC do its workreturn oldValue;
}
Iterator
ArrayList内部通过实现Iterator接口实现了一个迭代器,如下代码所示(省略部分代码):
- 每次调用迭代器的next()方法时,都会执行checkForComodification()方法的校验逻辑;
- checkForComodification()方法主要职责就是校验迭代器内属性expectedModCount和ArrayList类中属性modCount是否相等,不相等就抛出ConcurrentModificationException异常。
迭代器中的remove()方法,首先会调用checkForComodification()方法来校验当前数组的修改次数是否相等;然后会调用ArrayList类中的remove()方法完成删除;最后再将执行删除操作后ArrayList类中modCount属性的最新值赋给expectedModCount以保持两值相等。
private class Itr implements Iterator<E> {int cursor; // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;@SuppressWarnings("unchecked")public E next() {checkForComodification();}public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}
}
ArrayList#removeIf
想要删除数组中一个元素还可以使用ArrayList类的removeIf()方法,源代码逻辑可以参考下面六个步骤:
- 将modCount赋值给removeIf()方法局部变量expectedModCount;
- 使用for i 循环遍历数组每一个元素与目标删除元素比对,如果相等就将当前下标放入BitSet中标记为true(待删除元素);
- 校验局部变量expectedModCount与modCount是否相等,防止其它线程操作数组,如果两值不相等同样抛出ConcurrentModificationException异常;
- 再次for i循环遍历数组,利用BitSet完成删除目标元素、原地移动元素;
- 再校验一次局部变量expectedModCount与modCount是否相等,同样防止同时有其它线程在操作数组;
- 将modCount自增加一;
ArrayList删除元素的细则相关推荐
- java arraylist删除元素_java集合类ArrayList操作之删除remove某些元素的案例分析
在java开发中,会经常出现需要删除java ArrayList的某些元素的场景,比如从在线用户列表的ArrayList中删除离线用户的ArrayList,但有的人会出现循环在线用户ArrayList ...
- [ArrayList删除元素] 你需要了解的ArrayList如何安全的删除重复元素/ list去重
学习笔记使用 ArrayList特点:动态数组结构,元素有序,可重复的一个集合 import java.util.ArrayList; import java.util.Iterator; impor ...
- 如何在Java中处理ConcurrentModificationException? 在循环中从ArrayList中删除元素时要当心...
从Java中从ArrayList中删除元素时常见的问题之一是ConcurrentModificationException. 如果您对索引使用经典的for循环或增强的for循环,并尝试使用remove ...
- Java 集合中遍历删除元素抛异常的原因,从ArrayList说起
文章目录 使用for删除遗漏元素的原因: 使用foreach删除报错的原因: 其它集合的删除方法 删除集合元素的工具类 ArrayList删除元素的方式. 使用for循环删除.会遗漏删除的元素 使用f ...
- java arraylist 删除回车符_2种Java删除ArrayList中的重复元素的方法
这篇文章将给出两种从ArrayList中删除重复元素的方法,分别是使用HashSet和LinkedHashSet. ArrayList是Java中最常用的集合类型之一.它允许灵活添加多个null元素, ...
- foreach迭代ArrayList时,真的不能删除元素吗?
ArrayList是java开发时非常常用的类,常碰到需要对ArrayList循环删除元素的情况.这时候大家都不会使用foreach循环的方式来遍历List,因为它会抛java.util.Concur ...
- arraylist删除指定元素_面试官:谈谈常用的Arraylist和Linkedlist的区别
Arraylist:底层是基于动态数组,根据下表随机访问数组元素的效率高,向数组尾部添加元素的效率高:但是,删除数组中的数据以及向数组中间添加数据效率低,因为需要移动数组. 例如最坏的情况是删除第一个 ...
- 大剑无锋之ArrayList中使用增强for循环能删除元素吗?【面试推荐】
好久没写java代码,前几天面试被问到不少java的问题,其中一个接下来要说的. 先看几段代码. 第一段(集合中两个元素,判断条件是第一个元素) ArrayList<String> lis ...
- Arraylist理解(3)删除元素
第三次强调,ArrayLIst是一个普通的类. 好,现在我们来讨论一下数组的删除,我们知道数组一但在堆内存中创建出来,数组长度是不可变的,看以下源码: 添加10个用户 比如我们要把"周八&q ...
最新文章
- NYOJ练习题 又见Alice and Bob
- 人行联网核查更新_又一批新职业公布,学互联网技术,等于站在就业“风口”...
- 2019.04.06 电商04 模板嵌套
- mysql申请审核系统_Mysql审核工具archery
- c++11标准:匿名函数(匿名表达式)lambda
- php 走马灯轮播,Vue.js轮播图走马灯代码实例(全)
- 推荐系统实践:从多领域优化到AutoML框架
- [转载] 朴素贝叶斯python实现预测_Python实现朴素贝叶斯分类器的方法详解
- 【机器人】机械臂与动捕Nokov的深入了解
- php 四级联动插件,JavaScript_jQuery实现的多选框多级联动插件,jQuery 实现的多选框联动插件 - phpStudy...
- Citrix Xendesktop虚拟化桌面和深信服VSP安全桌面的技术对比
- 系统越用越臃肿,你需要的系统瘦身技巧.
- matlab矩阵指定行求和,在matlab中对矩阵元素求和的有效(最快)方法
- 30天自制操作系统——自写设计
- shimano 型号详解 (zz)
- udal导mysql_teledb-udal实践分享
- dataframe更改columns
- chrome调试与设置 remote设备调试
- 7-1 sdut-Collection(Map)-1 读中国载人航天史,汇航天员数量,向航天员致敬
- lv双肩包尺寸对照表_lv双肩包mini尺寸对照表
热门文章
- 什么是云原生的应用?
- beforeSend 出现跨域问题,header里直接设置token就没问题----Day1
- 【CHATGPT-3.5】如何使用ChatGPT的同时并学习记忆
- 在C语言中使用二分法算法思想解决猜商品价格问题
- python开发简历自我介绍范文_你们简历上的自我介绍怎么写的?
- 市值一夜间蒸发千亿,拼多多离不开黄峥?
- JAVA编写学校超市选址问题_中小型超市商品管理系统设计与实现【开题报告+文献综述+毕业论文】.docx...
- echarts中国地图边缘设置阴影投影效果,并添加散点,大小根据数值改变
- python 处理Bus Hound 数据
- MOSS--SharePoint 开发学习一些总结