2017-06-05 148 views
1

枚舉是故障安全的。失效安全迭代器將用於克隆原始集合。那麼爲什麼它會引發concurrentModificationException?請澄清。枚舉拋出concurrentModification異常。爲什麼?

請找我的代碼:

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) 
+3

Vector和枚舉已過時修改代碼 - 使用'ArrayList'和'Iterator'代替。 – assylias

+1

是的,如果你要從書本和教程中學習java,你可能需要找到一些在過去幾十年中寫的東西。如果他們在某所學校爲你教授這些東西,2017年,你可能想換個學校。 –

+0

@assylias使用Enumeration的ArrayList拋出ConcurrentModificationException。我懷疑這是爲什麼枚舉失敗時枚舉引發此異常。 – user6426361

回答

0

枚舉錯誤消息是故障安全。

正確。 (允許某些語言困難。)

失效安全迭代器將對克隆原始集合起作用。

正確。 (允許一些語言困難。)

那麼它爲什麼會引發concurrentModificationException?

因爲不涉及克隆。

克隆在哪裏?

1

您的枚舉在內部使用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幾乎不推薦使用。你應該propably使用一個列表,而不是:

正確的列出了進口(不要使用這個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(); 
    } 
} 

而且請注意,您可以將界面用作通常首選使用實施的類型。

編輯:你的例子

看,也許你真正需要的是一個隊列:

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 

此作品與您的例子。有關集合的更多信息請參見The official Collections Java Trail

+0

我也認爲你應該使用一種更年輕的教程來學習java。矢量通常不再使用。尤其不在教程中。我手邊沒有任何英文輔導,我知道這很好。但是你應該會發現一些非常快的 – Dennux

+0

(但它已經使用了'Iterator',因爲'Collections.enumeration'使用了'Iterator'。) –

+0

@David Conrad:就是這一點。這正是我的觀點。請仔細閱讀我的答案,並考慮枚舉在內部使用Iterator時發生的情況。看看我答案中的第一句話... – Dennux

2

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 
} 
0

您正在使用不支持已刪除方法的枚舉。一旦創建了一個枚舉,那麼當您執行從矢量中刪除時,它會測試checkForComodification .so,modCount增加並且expectedModCount不會被修改。

final void checkForComodification() { 
      if (modCount != expectedModCount) 
       throw new ConcurrentModificationException(); 
     } 

請用iterator

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(); 

     } 

    } 
相關問題