小心修改集合的大小

本文介绍Java新集合库,其去掉方法同步提升性能,但存在数据一致性问题,采用快速失败机制。通过示例展示遍历集合时修改大小会抛异常,还给出解决元素删除问题的方法,一是集合单处使用,用Iterator的remove方法;二是多处使用,不修改或clone集合。

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

### Java 集合框架中的集合与静态集合 在Java中,集合是指一系列对象的容器,这些对象可以被存储、检索和操作。Java集合框架位于`java.util`包中[^1]。 #### 动态集合的特点 动态集合允许在其生命周期内的任何时间点添加或移除元素,其大小不是固定的。例如,`ArrayList`继承了`AbstractList`并实现了`List`接口,作为一个数组队列提供了动态调整大小的能力以及相关的添加、删除、修改、遍历等功能[^4]。同样地,对于`Set`接口的不同实现类如`HashSet`、`LinkedHashSet`(它是`HashSet`的一个子类)、`TreeSet`也支持动态增删改查的操作[^2]。 #### 静态集合的概念 相比之下,“静态集合”并不是官方术语,在这里假设指的是通过工具类如`Collections`来创建不可变或者固定尺寸的集合实例的情况。这类集合一旦初始化完成就不能再改变其中的内容;如果尝试对其进行结构性修改,则会抛出异常。`Collections.unmodifiableCollection()`系列方法就是用来返回一个受保护视图的方法之一,该视图内部封装了一个原始可变集合,并阻止外界对其成员进行更改[^3]。 因此,主要区别在于: - **灵活性**:动态集合适用于需要频繁变更数据的应用场景;而静态集合更适合于那些希望确保某些特定时刻的数据状态不会发生变化的情形。 - **安全性**:由于无法对外界暴露修改权限,所以基于现有集合构建出来的只读版本能够有效防止意外篡改带来的风险。 ```java // 创建一个动态列表 List<String> dynamicList = new ArrayList<>(); dynamicList.add("Element"); // 将上述列表转换成不可变形式 List<String> staticList = Collections.unmodifiableList(dynamicList); try { staticList.add("Another Element"); // 这里将会引发UnsupportedOperationException } catch (Exception e) { System.out.println(e.getMessage()); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值