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;
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);
return sb.toString();
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
为什么会发生这样的结果呢?这是因为
"当使用 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而依赖于索引当然更不会出现异常.
代码下载:
http://www.blogjava.net/Files/sitinspring/ConcurrentModificationTest20071203210937.rar
分享到:
相关推荐
HashMap和List遍历方法及如何遍历删除元素总结 HashMap和List都是Java中最常用的数据结构,它们都可以用来存储和操作数据。然而,在遍历和删除元素时,需要小心地处理,以免出现问题。下面总结了HashMap和List的...
这段代码将抛出 `java.util.ConcurrentModificationException` 异常,因为在遍历 HashMap 的元素过程中删除了当前所在元素,下一个待访问的元素的指针也由此丢失了。 2. 正确的删除方法 正确的删除方法是使用迭代...
在Java编程中,遍历并删除集合(如List或Set)中的元素是一项常见的操作,但如果不正确地执行,可能会导致`ConcurrentModificationException`异常。这个异常通常在尝试修改正在迭代的集合时出现,因为Java的集合迭代...
在Java编程中,遍历并删除List中的元素是一项常见的操作,但如果不小心处理,可能会遇到错误,如`ConcurrentModificationException`。以下是几种常见的遍历删除List元素的方法及其注意事项: 1. **通过增强的for...
hasNext() 方法用于判断集合中是否还有未被遍历的元素,next() 方法用于返回集合中的下一个元素,remove() 方法用于删除集合中的上一个元素。 Iterator 接口主要用于遍历集合元素,而不是提供盛装对象的能力。因此...
这个示例代码尝试在遍历 ArrayList 时删除其中的一个元素,这将导致 ConcurrentModificationException 异常。 那么,为什么会抛出这个异常呢?我们可以通过查看 ArrayList 的源码来了解原因。ArrayList 的 iterator...
- 在多线程环境下,不要在遍历过程中修改HashMap,否则可能会抛出`ConcurrentModificationException`。如果需要在遍历中修改,可以使用`Iterator.remove()`方法,或者使用`CopyOnWriteArrayMap`等线程安全的集合。 -...
5. **异常处理**:在执行批量删除时,应捕获并处理可能出现的异常,例如`NoSuchElementException`或`ConcurrentModificationException`。 6. **性能考量**:批量删除操作的时间复杂度与所选数据结构和删除策略有关...
- 在遍历`Map`时,如果在遍历过程中尝试修改`Map`(例如添加或删除元素),可能会引发`ConcurrentModificationException`异常。因此,在遍历的同时不要修改`Map`。 - 使用流API遍历时,虽然代码更简洁,但性能上可能...
当你想在迭代过程中删除元素时,应该使用`Iterator`的`remove()`方法,而不是直接调用集合的`remove()`方法。这样,`Iterator`会正确处理集合的内部状态,避免异常: ```java List<String> list = new ArrayList...
在Java编程中,遍历并删除List或Map中的元素是一个常见的任务,但如果不理解其内部机制,可能会导致一些未预期的问题。本文将深入探讨在Java中如何安全地在List和Map遍历过程中删除元素。 首先,我们来看List的遍历...
在Java编程中,集合类遍历的同时进行删除操作是一个常见的需求,但如果不正确地执行,可能会导致`ConcurrentModificationException`。这个问题主要出现在迭代器正在遍历集合时,集合本身被修改的情况。以下是对这个...
在Java编程中,遍历并删除List集合是一个常见的操作,但在实际编程中,如果不使用正确的方法,可能会导致`java.util.ConcurrentModificationException`异常。本文主要针对这个面试题,详细讲解如何在遍历List的同时...
Java中遍历ConcurrentHashMap的四种方式详解 Java中遍历ConcurrentHashMap的四种方式详解是Java开发中一个非常重要的知识点。ConcurrentHashMap是Java中一种高效且线程安全的HashMap实现,它提供了高效的读写操作...
这种方法通过迭代器(Iterator)来遍历列表,并在遍历过程中删除重复的元素。这种方式可以有效地避免`ConcurrentModificationException`异常。 ```java Iterator<Integer> iterator = list.iterator(); while ...
如果在遍历过程中需要移除元素,必须使用`it.remove()`,直接调用`list.remove()`会导致并发修改异常(ConcurrentModificationException)。 ### 第二种:增强型for循环(foreach) ```java for (A a : list) { /...
容器是用来存储和管理对象的集合类,而迭代器则是用来遍历和访问容器中元素的接口。本篇将详细介绍几种常见的容器类(如LinkedList、Vector、ArrayList和Hashtable)以及它们的迭代器用法。 1. **LinkedList**: ...
在面试中,除了基本的遍历方式,还可能考察一些高级话题,如并发遍历(ConcurrentModificationException)、性能优化(如避免在循环中调用`size()`方法)以及如何处理null元素等。同时,理解不同集合类的底层实现和...
在本实例中,我们将深入探讨如何使用`foreach`循环遍历集合元素,并理解其工作原理以及可能遇到的问题。 首先,让我们看下给出的代码示例: ```java import java.util.*; public class ForeachTest { public ...