转自http://hi.baidu.com/notyetfish/blog/item/aa744738393c26cad56225b4.html
在对一个map进行迭代遍历并删除一些符合条件的键值对的时候,容易出现
java.util.ConcurrentModificationException 这个异常。
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:787)
at java.util.HashMap$KeyIterator.next(HashMap.java:823)
解决办法如下:
import java.util.*;
public class TestMap {
public TestMap() {
}
public static void main(String[] args) {
java.util.Map m = new java.util.HashMap();
m.put("aaa", "lizongbo ");
m.put("bbb", " lizongbo");
m.put("ccc", "lizongbo ");
m.put("ddd", " lizongbo");
m.put("eee", "lizongbo");
m.put("fff", "lizongbo");
m.put("ggg", "lizongbo");
m.put("adads", "lizongbo");
m.put("dffd", "lizongbo");
m.put("dcxv", "lizongbo");
m.put("lizongbo", "lizongbo");
m.put("ert", "lizongbo");
m.put("544", "lizongbo ");
Iterator iterator = m.keySet().iterator();
while (iterator.hasNext()) {
String sessionId = (String) iterator.next();
if ("ggg".equals(sessionId) || "lizongbo".equals(sessionId) ||
"544".equals(sessionId)) {
iterator.remove(); //这行代码是关键。
m.remove(sessionId);
}
}
System.out.println(m.get("ggg"));
System.out.println(m.get("lizongbo"));
System.out.println(m.get("544"));
}
当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行, java.util.ConcurrentModificationException 异常也将被抛出。
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
有意思的是如果你的 Collection / Map 对象实际只有一个元素的时候, ConcurrentModificationException 异常并不会被抛出。这也就是为什么在 javadoc 里面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
分享到:
相关推荐
在Java编程中,`java.util.ConcurrentModificationException` 是一个常见的运行时异常,通常发生在尝试并发修改集合时。这个异常的产生是由于集合类(如HashMap)的非线程安全特性,当你在一个线程中使用迭代器遍历...
`java.util.ConcurrentModificationException` 是一个在 Java 中常见的运行时异常,它通常发生在多线程环境中,当一个线程正在遍历一个集合(如 `ArrayList`, `HashMap` 等),而另一个线程同时尝试修改这个集合时。...
在这个例子中,当我们试图在遍历过程中删除一个元素时,迭代器会检测到Map的结构已被改变,从而抛出异常。这是因为迭代器在内部维护了一个指向集合的索引,当集合结构发生变化时,这个索引不再有效,导致迭代器无法...
但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除元素),Iterator将抛出ConcurrentModificationException异常。 Set接口是Collection接口的子接口...
这段代码将抛出 `java.util.ConcurrentModificationException` 异常,因为在遍历 HashMap 的元素过程中删除了当前所在元素,下一个待访问的元素的指针也由此丢失了。 2. 正确的删除方法 正确的删除方法是使用迭代...
- `java.util.Iterator`的改进:支持`remove()`操作,避免抛出`ConcurrentModificationException`。 ### 4. 性能优化 JDK 1.6对编译器和垃圾收集器进行了优化,提高了运行效率,例如: - **Server VM的改进**: ...
如果尝试这样做,编译器会抛出错误。例如,试图在循环中改变数组或集合的元素会报错。 4. **无法跳过元素或提前退出**: 由于`foreach`循环的底层实现,你不能使用`break`或`continue`语句来跳过当前元素或提前...
fail-fast迭代器在检测到集合结构被修改的情况下会快速抛出ConcurrentModificationException异常;fail-safe迭代器则不会抛出这种异常,因为它工作在集合的复制之上,如使用CopyOnWriteArrayList。迭代List集合的...
- 故障安全迭代器,如 ConcurrentHashMap 的迭代器,即使在并发修改时也能安全地工作,不会抛出异常。 3. **Java BlockingQueue**: - Java BlockingQueue 是并发编程的重要工具,属于 `java.util.concurrent` 包...
而java.util.concurrent包下的集合类则提供安全失败迭代器,它们在遍历时不会因为集合被修改而抛出异常,因为它们是基于集合的快照来实现的。 4. HashMap是一个用于存储键值对的集合。它基于哈希表的Map接口实现,...
快速失败(Fail-Fast)迭代器机制是指在用迭代器遍历集合的过程中,如果检测到集合在迭代过程中被修改了,就会迅速抛出ConcurrentModificationException异常。快速失败机制的迭代器是为单线程设计的,因为它们不能...
即使知道某段代码可能抛出异常,也应该适当地捕获并处理,或者声明方法可能抛出的异常。 6. **资源管理不当**: 使用`FileInputStream`、`Socket`等需要手动关闭的资源时,忘记关闭可能会导致资源泄露。Java 7引入...
5. **遍历Map的迭代器** 对于Map,我们不能直接使用迭代器遍历键值对,但可以分别获取键集(keySet)和值集(values)的迭代器。或者使用`entrySet()`方法获取Entry迭代器,每个Entry包含键值对。 6. **并发迭代**...
由于HashMap不是线程安全的,一个线程在遍历HashMap的同时,另一个线程对HashMap进行修改(如添加、删除元素),会导致迭代器失效,从而抛出异常。 2. **数据不一致**:由于HashMap的内部实现,如resize操作,可能...
虽然在编译阶段可能没有问题,但在运行时,如果集合在迭代过程中被修改(添加、删除元素),可能会抛出`ConcurrentModificationException`。这是因为默认的迭代器不支持并发修改。为了安全地修改集合,可以使用`...
迭代器的使用遵循“fail-fast”原则,即如果在迭代过程中修改了集合,迭代器会抛出`ConcurrentModificationException`。 现在,让我们分析给定的文件`First.java`和`Student.java`。假设`First.java`是主程序,它...
- 不要捕获并忽略异常,而应处理异常或向上抛出。 - 不要随便使用`Exception`作为捕获类型,应尽可能精确到具体异常。 - 使用`try-with-resources`语句处理需要关闭的资源。 5. **并发编程**: - 尽量避免使用`...
在遍历 `HashMap` 或其他集合时,如果修改容器(如添加、删除元素或更改元素),可能会抛出 `ConcurrentModificationException`。为了安全地修改容器,应使用 `Iterator` 或 `Map.Entry` 进行迭代。 4. 接口中定义...
**强制规定**:在 JDK7 及以上版本中,`Comparator` 实现类需要满足以下三个条件,否则在使用 `Arrays.sort` 或 `Collections.sort` 时会抛出 `IllegalArgumentException` 异常。 - **条件一**:`x` 和 `y` 的比较...