迭代器如何同时从集合中读取和删除元素?
How does the iterator simultaneously read and delete elements from a collection?
我创建了以下代码。
我的 objective 是检查在读取集合时使用迭代器删除元素。
任何人都可以解释为什么在将 hashmap 的值集合添加到链表并为该列表创建迭代器后抛出 concurrentModificationException,但在将集合添加到列表后获得迭代器时不会抛出相同的异常?
我知道原因很简单,想要一些容易获得的东西,但我只是想确认我的想法是否正确。
还有2点。
1. 由于 hashmap 不是线程安全的,所以为什么我们不能在迭代器读取时向它添加任何元素?
2. 如果是,那么我们如何从地图中删除元素?
package com.Users;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
public class Temp{
public static void main(String arg[]){
HashMap<String, String> map=new HashMap();
map.put("A", "B");
map.put("C", "D");
LinkedList<String> list=new LinkedList<>();
//****** concurent exception is thrown when ever line 1 is swapped with line 2 ******
Iterator<String> iterator=list.iterator(); //line no. 1
list.addAll(map.values()); //line no. 2
//******************
while(iterator.hasNext()){
if(iterator.next().equals("B")){
iterator.remove();
}
}
System.out.println(list);
}
}
HashMap
上的迭代器本质上是 fail-fast
,这实质上意味着它们会尽快中止操作,并立即暴露失败。
集合维护一个名为 modCount
的内部计数器。每当从集合中添加或删除项目时,此计数器都会被修改。
迭代时,在每次调用 next() 时,会将 modCount 的当前值与初始值进行比较。如果不匹配,它会抛出 ConcurrentModificationException
中止整个操作。
- As hashmap is not threadsafe, so is it why that we can't add any element to it while the iterator is reading?
我们无法修改集合,因为我们正在迭代集合,因为大多数集合(例如 ArrayList、HashMap)默认具有快速失败的迭代器。
- If yes, then how are we able to remove elements from the map?
我们能够删除您示例中的元素,因为我们在 iterator.remove()
中使用了迭代器的 remove()
方法。
如果我们使用集合的 remove()
方法,这也会抛出 ConcurrentModificationException
。
请阅读 this 以获得详细说明。
我创建了以下代码。 我的 objective 是检查在读取集合时使用迭代器删除元素。 任何人都可以解释为什么在将 hashmap 的值集合添加到链表并为该列表创建迭代器后抛出 concurrentModificationException,但在将集合添加到列表后获得迭代器时不会抛出相同的异常?
我知道原因很简单,想要一些容易获得的东西,但我只是想确认我的想法是否正确。
还有2点。 1. 由于 hashmap 不是线程安全的,所以为什么我们不能在迭代器读取时向它添加任何元素? 2. 如果是,那么我们如何从地图中删除元素?
package com.Users;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
public class Temp{
public static void main(String arg[]){
HashMap<String, String> map=new HashMap();
map.put("A", "B");
map.put("C", "D");
LinkedList<String> list=new LinkedList<>();
//****** concurent exception is thrown when ever line 1 is swapped with line 2 ******
Iterator<String> iterator=list.iterator(); //line no. 1
list.addAll(map.values()); //line no. 2
//******************
while(iterator.hasNext()){
if(iterator.next().equals("B")){
iterator.remove();
}
}
System.out.println(list);
}
}
HashMap
上的迭代器本质上是 fail-fast
,这实质上意味着它们会尽快中止操作,并立即暴露失败。
集合维护一个名为 modCount
的内部计数器。每当从集合中添加或删除项目时,此计数器都会被修改。
迭代时,在每次调用 next() 时,会将 modCount 的当前值与初始值进行比较。如果不匹配,它会抛出 ConcurrentModificationException
中止整个操作。
- As hashmap is not threadsafe, so is it why that we can't add any element to it while the iterator is reading?
我们无法修改集合,因为我们正在迭代集合,因为大多数集合(例如 ArrayList、HashMap)默认具有快速失败的迭代器。
- If yes, then how are we able to remove elements from the map?
我们能够删除您示例中的元素,因为我们在 iterator.remove()
中使用了迭代器的 remove()
方法。
如果我们使用集合的 remove()
方法,这也会抛出 ConcurrentModificationException
。
请阅读 this 以获得详细说明。