2017-06-05 170 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(); 

     } 

    } 
相关问题