引用http://www.blogjava.net/sitinspring/archive/2007/12/03/165006.html
在以下四种遍历过程中,前两种会抛出ConcurrentModificationException,而后两种方法是正确的.
Department类:
package com.sitinspring;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Department {
private String name;
private List<Member> memberSheet;
public Department(String name) {
this.name = name;
}
public void addMemer(Member member) {
if (memberSheet == null) {
memberSheet = new ArrayList<Member>();
}
memberSheet.add(member);
}
public void printMemberSheet() {
System.out.println("----部门" + name + "人员名单---");
for (Member member : memberSheet) {
System.out.println(member);
}
}
/**
* 里面的四个清除过程请分别独立执行
*
*/
public void removeYoungerFromMemberSheet() {
// 遍历一:这个处理会抛出java.util.ConcurrentModificationException
for (Member member : memberSheet) {
if (member.getAge() < 30) {
memberSheet.remove(member);
}
}
// 遍历二:这个处理也会抛出java.util.ConcurrentModificationException
for (Iterator it = memberSheet.iterator(); it.hasNext();) {
Member member = (Member) it.next();
if (member.getAge() < 30) {
memberSheet.remove(member);
}
}
// 遍历三:这个处理调用Iterator 本身的方法 remove(),会正常执行
for (Iterator it = memberSheet.iterator(); it.hasNext();) {
Member member = (Member) it.next();
if (member.getAge() < 30) {
it.remove();
}
}
// 遍历四:这个处理不依赖Iterator,也会正常执行
for (int i=0;i<memberSheet.size();i++) {
Member member = memberSheet.get(i);
if (member.getAge() < 30) {
memberSheet.remove(member);
}
}
}
public String toString() {
return name;
}
public String getName() {
return name;
}
public static void main(String[] args) {
Department resarchDept = new Department("研发部门");
resarchDept.addMemer(new Member("张三", 38));
resarchDept.addMemer(new Member("李四", 24));
resarchDept.addMemer(new Member("王五", 30));
resarchDept.addMemer(new Member("钱七", 22));
resarchDept.addMemer(new Member("孙八", 39));
resarchDept.addMemer(new Member("周九", 30));
resarchDept.removeYoungerFromMemberSheet();
resarchDept.printMemberSheet();
}
}
Member类:
package com.sitinspring;
public class Member{
private String name;
private int age;
private Department department;
public Member(String name,int age){
this.name=name;
this.age=age;
}
public String toString(){
StringBuffer sb=new StringBuffer();
sb.append("员工名="+name);
sb.append(" 年龄="+age);
if(department!=null){
sb.append(" 所属部门="+department);
}
return sb.toString();
}
public void changeNewDepartment(Department newDepartment) {
department.removeMemer(name);
newDepartment.addMemer(this);
}
public String getName() {
return name;
}
public void setDepartment(Department department) {
this.department = department;
}
}
为什么会发生这样的结果呢?这是因为
"当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行, java.util.ConcurrentModificationException 异常也将被抛出。
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。"
上述这段资料来自http://hi.baidu.com/xjenator/blog/item/23b235a89041d4b0ca130c16.html.
java.util包中很多迭代器都是所谓的fail-fast迭代器.这些迭代器如果发现集合被修改,而且不是通过迭代器本身,那么抛出一个异常进行清除-ConcurrentModificationException-从而避免不安全行为的发生.
因此,第三种采用it.remove();不会出现任何异常,而第四不依赖于Iterator而依赖于索引当然更不会出现异常.
分享到:
相关推荐
Task task = BlockingCollectionUtil.AddTakeBlockingCollectionAsync(); Task.WaitAny(task); BlockingCollectionUtil.TryTakeBlockingCollection(); ConcurrentBagUtil.Test(); ConcurrentDictionaryUtil....
1、 为SavingsAccount类和CheckingAccout类的取款行为分别定义异常类NotEnoughBalanceException和OverdraftLimitExceededException,当SavingsAccount类中取款超过余额或者当CheckingAccount类产生透支超过最大额度...
集合例子代码,自定义异常例子代码,希望对初学者有帮助
Java 课件 (包括基础语法,数组与语句,面向对象编程,java异常处理,java常用基础类,java集合与泛型)
Concurrent - 函数式并发原语的集合
泛型集合解释的非常好泛型集合泛型集合泛型集合解释的非常好泛型集合泛型集合泛型集合解释的非常好泛型集合泛型集合泛型集合解释的非常好泛型集合泛型集合
C# 正则表达式 集合 C# 正则表达式 集合 C# 正则表达式 集合
智能文案数据集合智能文案数据集合智能文案数据集合智能文案数据集合智能文案数据集合智能文案数据集合智能文案数据集合智能文案数据集合智能文案数据集合智能文案数据集合智能文案数据集合智能文案数据集合智能文案...
掌握集合的概念、体系结构、分类及使用场景 2)了解Set接口及主要实现类(HashSet、TreeSet) 3)了解List接口及主要实现类(ArrayList、LinkedList、Vector) 4)了解Map接口及主要实现类(HashMap、TreeMap、...
常用的HTTP端口错误集合,包括常见的404,500等,
js事件集合js事件集合事件集合事件集合事件集合,js事件集合,js事件集合
c#官方线程安全集合源码,concurrentBag concurrentqueue,concurrentset,concurrentDictionary,concurrentSet等
Java基础之常用类集合,异常、IO文件等基础使用
户型集合户型集合户型集合户型集合户型集合户型集合
在.NET FCL为我们提供了很多集合类型,是编程中非常有力的工具。泛型集合主要在 System.Collections.Generic名称空间中,而非泛型集合主要在System.Collections,首先抛出 结论:如果在C#2.0版本以上,尽量使用泛型...
java泛型集合 java集合 集合 java Collection 排序 集合排序
高等数学公式集合高等数学公式集合高等数学公式集合高等数学公式集合高等数学公式集合高等数学公式集合高等数学公式集合
⑹ 设计一个菜单,具有输入集合元素、求集合A、B的交C、求集合A、B的并D、求集合A与B的对称差E、退出等基本的功能。 3.测试数据:字符型和整形由同学们自定,但集合A、B的元素个数不得少于15个。
网上有好多实体转另一个实体的方法,但是几乎没有实体集合直接转另一个实体集合的工具类,自己写了一个,供大家使用。其实原理很简单,就是泛型。
绝对犀利。怀恋以前老师讲课时光,因为有你我才变成了今天的程序猿。 java 异常、IO、集合