`
isiqi
  • 浏览: 16551744 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

小心修改集合的大小

阅读更多

Java中最常使用的就是集合了,而且处于性能的考虑,现在大部分人都不再使用Vector这种方法同步的集合了。新的集合库带来了更快的性能,同时也带来了更多错误使用的可能。新集合库性能的提升主要就是去掉了方法同步,可想而知,同步访问时必然存在数据一致性问题。为了能使程序不会因为数据的不一致而造成其它错误,新集合库在设计时采用了快速失败机制(Fast-Fail),就是每次遍历集合时都会判断当前集合大小是否被修改,如果被修改,马上抛出ConcurrentModificationException异常,停止程序继续运行。因此集合初始化完成后,应避免在另一处被修改大小。看下面这个例子:
packagecom.bhr.ioat.testcollection;
importjava.util.*;
publicclassTestRemove
{
publicstaticvoidmain(String[]args)
{
Collectioncltn=newArrayList();
for(inti=0;i<100000;i++){
cltn.add(newInteger(i));
}
newOtherThread(cltn).start();
try{
Thread.sleep(1000);//sleep1second,inordertoensurethenewthreadstartup.
}catch(Exceptione){
e.printStackTrace();
}
Iteratorit=cltn.iterator();
while(it.hasNext()){
Objectobj=it.next();
cltn.remove(obj);
//it.remove();
System.out.println("Removeoneelementfromcollection");
break;
}

}
}

classOtherThreadextendsThread
{
publicCollectioncltn_;
publicOtherThread(Collectioncltn){
cltn_=cltn;
//cltn_=(Collection)(((ArrayList)cltn).clone());
}

publicvoidrun(){
Iteratorit=cltn_.iterator();
while(it.hasNext()){
Objectobj=it.next();
System.out.println(obj);
}
}

}

程序很简单,开始初始化一个100000大小的ArrayList,然后传给另一个类,随后删除集合中的一个元素,你会发现马上就会抛出ConcurrentModificationException异常。
那是不是就不可以删除元素了?是不是应该继续使用Vector?当然不是,要不新集合的出现岂不是失去了意义。解决方法有两个,(1)集合只在一处被使用,这自然没有并发问题,不过还是不可以大胆修改,如果循环中删除集合中的元素,一定要调用Iterator的remove方法,而不是Collection的remove方法,前者删除后会修改Iterator的一个值,使得循环以为集合没被修改,可以继续进行,而调用后者没有修改Iterator中的值,继续循环同样会抛出异常。至于添加元素,Iterator中没有提供相应方法,所以如果在循环中添加,添加后就只能跳出循环了。(2)同一个集合在多处被使用,索性不要删除了,本来这种情况就不应该修改集合大小,如果你决得集合大小的修改不会影响程序的正常逻辑,那么使用时只好clone一个了。
上面只是实际中总结得一点经验,如果大家有更好得方法,可以交流一下。

E-mail:bbs_9527@yahoo.com.cn

分享到:
评论

相关推荐

    Linux命令大全(Linuxidc.com修改版)

    "Linux命令大全(Linuxidc.com修改版)"是一个集合了大量Linux命令及其用法的参考文档,方便用户随时查阅。 1. **基础命令** - `ls`: 列出目录内容,用于查看当前目录下的文件和子目录。 - `cd`: 更改当前工作目录...

    Linux常用命令集合

    6. **rm**:删除文件或目录,小心使用,因为这个命令通常是不可逆的。 7. **cat**:合并并显示文件内容,常用于查看小型文本文件。 8. **more**:分页显示文件内容,按空格键向下翻页,回车键向下一行,Q键退出。 9....

    Linux命令大全(修改版)

    Linux命令大全(修改版)是针对Linux操作系统中的命令行工具进行详尽介绍的资源集合,主要面向想要深入理解和掌握Linux操作系统的用户。这份修改版可能包含了一些原版中没有的更新或者优化,使得学习和查询更为方便。...

    linux常见操作命令集合,方式使用查询

    以下是对“Linux常见操作命令集合”中一些重要命令的详细解释: 1. **ls** - 列出目录内容:`ls`命令用于查看当前目录中的文件和子目录。加上 `-l` 参数可以显示详细信息,如权限、大小、日期等;`-a` 参数会显示...

    linux命令大全(修改版)

    Linux命令大全(修改版)是针对Linux操作系统中常用命令的一个集合,旨在帮助用户更好地理解和掌握在终端中执行的各种操作。这个资源包含了316个不同的命令,覆盖了系统管理、文件操作、网络通信、进程控制等多个方面...

    Linux命令大全(修改版) (电子书)

    本文将深入探讨标题中的"Linux命令大全(修改版)",这是一份包含了316个常用Linux命令的集合,旨在帮助用户更好地理解和操作Linux系统。 在Linux环境中,命令行接口(CLI)是执行任务的主要方式,它提供了高效、直接...

    所有Linux命令集合,全部来自网络资源 .zip

    你可以根据文件名、大小、修改日期等条件进行搜索。 13. `sudo`:以超级用户权限运行命令。许多系统管理任务需要管理员权限,`sudo`就是为此设计的。 14. `apt` 或 `yum`:软件包管理器。在Ubuntu等Debian系系统中...

    AIXLVM镜像同步原理[文].pdf

    在增加文件系统大小的同时会自动扩充逻辑卷的大小,因此要增加文件系统大小,可直接修改文件系统的size 属性值,不必先去增加逻辑卷大小,然后再增加文件系统大小。 但是,减小LV的容量在AIX系统中,LV的大小只可...

    藏经阁-Java开发手册(嵩山版)灵魂15问-123.pdf

    这是因为Apache Beanutils在进行属性拷贝时存在一些问题,例如它不能正确地处理一些类型的属性,例如日期类型和集合类型。此外,Apache Beanutils还存在性能问题,它的性能较差,特别是在大规模数据的拷贝中。 2.为...

    自己经历的面试题参考2

    - 如果不使用指针变量而直接通过地址操作,则需要更加小心,因为这可能会导致程序不稳定。 ```c *(int *)0x0012ff7c = 0x100; // 直接赋值 ``` #### 二、数组的基本概念 1. **数组的内存布局** - 数组是一系列...

    Java编程中常见的坑

    使用`Arrays.asList()`方法将数组转换为集合时需要注意,这种方法返回的是一个固定大小的列表,并且不允许修改集合(比如添加或删除元素)。如果尝试修改该集合,将会抛出`UnsupportedOperationException`。 将集合...

    c语言堆和链表.doc

    这种实现方式在处理未知大小的数据集合时非常灵活,但也需要小心管理内存,以避免内存泄漏或栈溢出等问题。 总之,堆和链表是C语言中处理动态数据的关键概念,掌握它们对于编写高效、可靠的程序至关重要。无论是...

    易语言文件尾部附加数据

    在计算机文件系统中,文件是一个存储在磁盘上的数据集合,每个文件都有一个起始位置和一个结束位置。当我们要在文件尾部附加数据时,意味着我们不修改文件原有的内容,而是增加新的数据到文件的末尾。这种操作常见于...

    在Python中使用dict和set方法的教程

    而字典可以直接通过键快速定位到值,不受其大小的影响。 在Python中创建字典有两种常用的方法:一种是直接使用大括号`{}`进行初始化,并使用冒号`:`分隔键和值;另一种是使用`dict()`构造函数。字典的键必须是可...

    阿里开发手册

    如果需要在遍历过程中修改集合,应该使用迭代器提供的remove方法或者显式地使用索引进行操作。 十一、为什么禁止工程师直接使用日志系统(Log4j、Logback)中的API? 直接使用日志框架的API可能会导致日志的格式和...

    DOS命令活用实例随手查之(3)命令D-E活用实例

    同时,它还可以显示文件的文件名、扩展名、大小、修改日期和时间、累计大小以及磁盘上剩余的可用空间。 Dir命令还支持各种参数,比如/w参数可以以宽格式显示文件列表,即在每一行上显示更多的文件名或目录名;/p...

    C#基础资料

    这意味着修改一个引用类型的变量会影响到所有指向同一数据的其他变量。 - **示例**:类(class)、接口(interface)、数组(array)和委托(delegate)等都属于引用类型。 - **特点**:引用类型的变量大小不是固定的,取...

    C++数据结构实现之Array.zip

    因此,对于数组的操作需要特别小心,以防止意外修改。 6. **多维数组**:C++支持多维数组,例如二维数组可以表示矩阵。例如,`int matrix[3][4]`创建了一个3行4列的矩阵。访问元素的方式是`matrix[i][j]`,其中i是...

Global site tag (gtag.js) - Google Analytics