簡體   English   中英

枚舉是在拋出concurrentModification異常。 為什么?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM