Java遍历时删除List、Set、Map中的元素(源码分析)
在对List、Set、Map执行遍历删除或添加等改变集合个数的操作时,不能使用普通的while、for循环或增强for。会抛出ConcurrentModificationException异常或者没有达到删除的需求。在遍历时删除元素,需要使用迭代器的方式。
ArrayList源码中说明的报异常原因:
* <p>The iterators returned by this class's <tt>iterator</tt> and
* <tt>listIterator</tt> methods are <i>fail-fast</i>: if the list is
* structurally modified at any time after the iterator is created, in any way
* except through the iterator's own <tt>remove</tt> or <tt>add</tt> methods,
* the iterator will throw a {@link ConcurrentModificationException}. Thus, in
* the face of concurrent modification, the iterator fails quickly and cleanly,
* rather than risking arbitrary, non-deterministic behavior at an undetermined
* time in the future.<p>
(翻译:通过类的iterator和listiterator方法获取到的迭代器是快速失败迭代器:如果list在迭代器生成之后发生了结构性的改变,迭代器将抛出ConcurrentModificationException,但是当使用迭代器自己的remove或add方法时,不会抛出此异常。也就是说,当面对并发修改时,迭代器快速失败,而不是冒在未来不确定的时间发生不确定的行为的危险。)
*
* Note that the fail-fast behavior of an iterator cannot be guaranteed
* as it is, generally speaking, impossible to make any hard guarantees in the
* presence of unsynchronized concurrent modification. Fail-fast iterators
* throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>the fail-fast behavior of iterators
* should be used only to detect bugs.</i><p>
(翻译:需要注意的是迭代器不保证快速失败行为一定发生,因为一般来说不可能对是否发生了不同步并发修改做任何硬性的保证。快速失败迭代器会尽最大努力抛出ConcurrentModificationException异常。因此,写一个通过是否出现这种异常来判断是否正确的程序是错误的。快速失败行为的正确用法是仅用于检测异常。)
代码示例:
public class CollectionRemoveDemo {
public static void main(String[] args) {
ListRemove();
System.out.println("-----------------------------------------------------------------------------------------------");
SetRemove();
System.out.println("-----------------------------------------------------------------------------------------------");
MapRemove();
}
public static void ListRemove(){
List<String> strList = new ArrayList<String>();
strList.add("aaaa");
strList.add("bbbb");
strList.add("cccc");
strList.add("cccc");
strList.add("dddd");
for(String str : strList){
System.out.println(str);
}
System.out.println("init List size:" + strList.size());
Iterator<String> it = strList.iterator();
while(it.hasNext()){
String str = it.next();
if(str.equals("cccc")){
it.remove();
}
}
for(String str : strList){
System.out.println(str);
}
System.out.println("removed List size:" + strList.size());
}
public static void SetRemove(){
Set<String> strSet = new TreeSet<String>();
strSet.add("aaaa");
strSet.add("bbbb");
strSet.add("cccc");
strSet.add("cccc");//重复的数据将不会再次插入
strSet.add("dddd");
for(String str : strSet){
System.out.println(str);
}
System.out.println("Init Set size:" + strSet.size());
Iterator<String> it = strSet.iterator();
while(it.hasNext()){
String str = it.next();
if(str.equals("cccc")){
it.remove();
}
}
for(String str : strSet){
System.out.println(str);
}
System.out.println("removed Set size:" + strSet.size());
}
public static void MapRemove(){
Map<String, String> strMap = new TreeMap<String, String>();
strMap.put("a", "aaaa");
strMap.put("b", "bbbb");
strMap.put("c", "cccc");
strMap.put("d", "dddd");
for(String key : strMap.keySet()){
System.out.println(key + " : " + strMap.get(key));
}
System.out.println("Init Map size:" + strMap.size());
Iterator<Entry<String,String>> it = strMap.entrySet().iterator();
while(it.hasNext()){
Entry<String,String> strEntry = it.next();
if(strEntry.getKey().equals("c")){
it.remove();
}
}
for(String key : strMap.keySet()){
System.out.println(key + " : " + strMap.get(key));
}
System.out.println("removed Map size:" + strMap.size());
}
}
Java遍历时删除List、Set、Map中的元素(源码分析)的更多相关文章
- BIZ中model.getSql源码分析
功能:根据model.xml文件中配置的sql,获取对应的动态sql结果. 实例代码:String sql1 = model.getSql(dao.dbMeta());String sql2 = mo ...
- Spring中Bean命名源码分析
Spring中Bean命名源码分析 一.案例代码 首先是demo的整体结构 其次是各个部分的代码,代码本身比较简单,不是我们关注的重点 配置类 /** * @Author Helius * @Crea ...
- HashSet 添加/遍历元素源码分析
HashSet 类图 HashSet 简单说明 HashSet 实现了 Set 接口 HashSet 底层实际上是由 HashMap 实现的 public HashSet() { map = new ...
- Java并发编程笔记之Unsafe类和LockSupport类源码分析
一.Unsafe类的源码分析 JDK的rt.jar包中的Unsafe类提供了硬件级别的原子操作,Unsafe里面的方法都是native方法,通过使用JNI的方式来访问本地C++实现库. rt.jar ...
- 【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象
前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五 ...
- Netty中的ChannelPipeline源码分析
ChannelPipeline在Netty中是用来处理请求的责任链,默认实现是DefaultChannelPipeline,其构造方法如下: private final Channel channel ...
- Springboot中注解@Configuration源码分析
Springboot中注解@Configuration和@Component的区别 1.先说结论,@Configuration注解上面有@Component注解,所以@Component有的功能@Co ...
- java 集合与数组的互转方法,与源码分析
前言 java数组与集合需要互相转换的场景非常多,但是运用不好还是容易抛出UnSupportedOperationException.下面讲解一下互转的方法,以及结合源码分异常产生的原因 集合转数组 ...
- MapReduce中map并行度优化及源码分析
mapTask并行度的决定机制 一个job的map阶段并行度由客户端在提交job时决定,而客户端对map阶段并行度的规划的基本逻辑为:将待处理数据执行逻辑切片(即按照一个特定切片大小,将待处理数据划分 ...
随机推荐
- bzoj 4919: [Lydsy六月月赛]大根堆
Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质: ...
- django rest-framework 4.REST的认证和权限
目前,我们的API对谁可以编辑或删除代码段没有任何限制.我们想要一些更先进的行为,以确保:(这段话抄自官网) 代码段始终与创建者相关联. 只有身份验证的用户可以创建片段. 只有片段的创建者可以更新或删 ...
- Python SMTP邮件发送
SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件.HTML邮件以及带附件的邮件. Python对SMTP支持有smtplib和email两个模块: email负责构造邮件 ...
- Xamarin开发缺少的android_m2repository_rxx.zip下载地址以及MD5
android_m2repository_rxx.zip下载地址以及MD5, 注意:下载后需要改文件名,改为 MD5的值.zip 例如:android_m2repository_r29.zip 需改 ...
- TensorFlow 中文资源全集,官方网站,安装教程,入门教程,实战项目,学习路径。
Awesome-TensorFlow-Chinese TensorFlow 中文资源全集,学习路径推荐: 官方网站,初步了解. 安装教程,安装之后跑起来. 入门教程,简单的模型学习和运行. 实战项目, ...
- jquery选择器选取class
- Java Web -【分页功能】详解
分页简介 分页功能在网页中是非常常见的一个功能,其作用也就是将数据分割成多个页面来进行显示. 使用场景: 当取到的数据量达到一定的时候,就需要使用分页来进行数据分割. 当我们不使用分页功能的时候,会面 ...
- Linux下安装java的jdk和配置环境变量
每次感觉配这个超级简单 但是每次都要查下 记一下好了 Linux下安装jdk,步骤如下 1:下载jdk包:本章使用的为后缀为tar.gz的文件(不需要安装),如jdk-8u111-linux-x64. ...
- Python小代码_9_求水仙花数
for i in range(100, 1000): ge = i % 10 shi = i // 10 % 10 bai = i // 100 if ge ** 3 + shi ** 3 + bai ...
- js密码64加密
可以在客户端对密码进行简单的64位加密,服务端对应使用64位解密即可. /** * * Base64 encode / decode * * @author * @date * @email */ f ...