[英]Enumeration is throwing concurrentModification Exception. why?
枚舉是故障安全的。 故障安全迭代器將用於克隆原始集合。 那么為什么它會拋出concurrentModificationException? 請澄清。
請找我的代碼:
public static void main(String[] args) {
Vector<String> v=new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Enumeration en=(Enumeration) Collections.enumeration(v);
while(en.hasMoreElements())
{
String value=(String) en.nextElement();
System.out.println(value);
v.remove(value);//modifying the collection
}
}
找到下面的錯誤消息
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.Vector$Itr.checkForComodification(Unknown Source)
at java.util.Vector$Itr.next(Unknown Source)
at java.util.Collections$2.nextElement(Unknown Source)
at valar.org.src.EnumerationTest.main(EnumerationTest.java:24)
Collections.enumeration(Collection)
將從作為參數傳遞的集合中創建一個迭代器:
public static <T> Enumeration<T> enumeration(final Collection<T> c) {
return new Enumeration<T>() {
private final Iterator<T> i = c.iterator();
public boolean hasMoreElements() {
return i.hasNext();
}
public T nextElement() {
return i.next();
}
};
}
這意味着迭代器被支持到您在迭代器循環中刪除元素的集合,並且您無法刪除使用迭代器迭代的集合的元素。
您應該在enumeration()
調用中創建傳遞的Vector
的副本:
Enumeration<String> en = Collections.enumeration(new Vector<String>(v));
而作為一個側面說明,你應該有利於List
界面和ArrayList
實現了Vector
(即同步),並宣布泛型集合備件演員和增加代碼的類型安全。
所以它會給出這個代碼(我使用了Vector
因為它可能是一個不可修改的約束,但我指定了泛型,因為它甚至在遺留代碼中添加通常更簡單):
Vector<String> v = new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Enumeration<String> en = Collections.enumeration(new Vector<String>(v));
while (en.hasMoreElements()) {
String value = (String) en.nextElement();
System.out.println(value);
v.remove(value);// modifying the collection
}
您的枚舉在內部使用Iterator。 迭代元素時,不能使用向量本身來刪除項目。 你必須使用迭代器。 但是你無法訪問它。 改為創建一個迭代器:
public static void main(String[] args) {
final Vector<String> v = new Vector<String>();
v.add("Amit");
v.add("Raj");
// Use an Iterator to remove the value you are iterating over
final Iterator<String> iterator = v.iterator();
while (iterator.hasNext()) {
final String value = iterator.next();
System.out.println(value);
iterator.remove();
}
}
盡管Vector實際上已經被棄用了。 您應該可以使用List代替:
正確列表的導入(不要使用awt.List):
import java.util.ArrayList;
import java.util.List;
更改的代碼:
public static void main(String[] args) {
final List<String> v = new ArrayList<>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
final Iterator<String> iterator = v.iterator();
while (iterator.hasNext()) {
final String value = iterator.next();
System.out.println(value);
iterator.remove();
}
}
另請注意,您可以將接口用作Type,這通常是使用該實現的首選。
編輯:
看看你的例子,也許你真正需要的是一個隊列:
public static void main(String[] args) {
final Queue<String> v = new LinkedList<>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
System.out.println("Size: " + v.size());
for (String element = v.poll(); element != null; element = v.poll()) {
System.out.println(element);
}
System.out.println("Size: " + v.size());
}
輸出:
Size: 3
Amit
Raj
Pathak
Size: 0
這與您的示例相同。 有關集合的更多信息,請參閱官方集合Java Trail
枚舉是故障安全的。
正確。 (允許一些語言困難。)
故障安全迭代器將用於克隆原始集合。
正確。 (允許一些語言困難。)
那么為什么它會拋出concurrentModificationException?
因為沒有涉及克隆。
克隆在哪里?
您正在使用不支持刪除方法的Enumeration。一旦您創建了Enumeration,它就會測試checkForComodification。所以當您從向量中刪除時,modCount會增加,而expectModCount也不會被修改。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
請使用迭代器修改您的代碼
public static void main(String[] args) {
Vector<String> v = new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Iterator<String> it =v.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println(value);
it.remove();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.