簡體   English   中英

使用iterator和iterator.remove()時出現ConcurrentModificationException

[英]ConcurrentModificationException when using iterator and iterator.remove()

    private int checkLevel(String bigWord, Collection<String> dict, MinMax minMax)
{
    /*value initialised to losing*/
    int value = 0; 
    if (minMax == MinMax.MIN) value = 1; 
    else value = -1; 


    boolean go = true;

    Iterator<String> iter = dict.iterator();

    while(iter.hasNext())
    {
        String str = iter.next(); 
        Collection<Integer> inds = naiveStringSearch(bigWord, str);

        if(inds.isEmpty())
        {
            iter.remove();
        }

        for (Integer i : inds)
        {
            MinMax passin = minMax.MIN;
            if (minMax == MinMax.MIN) passin = minMax.MAX;

            int value2 = checkLevel(removeWord(bigWord, str, i), dict, passin); 
            if (value2 == -1 && minMax == minMax.MIN)
            {
                value = -1; 
                go = false;
            }
            if (value2 == 1 && minMax == minMax.MAX)
            {
                value = 1; 
                go = false; 
            }

        }

        if (go == false) break; 
    }


    return value;
}

錯誤:

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:810)
at java.util.HashMap$KeyIterator.next(HashMap.java:845)
at aStringGame.Main.checkLevel(Main.java:67)
at aStringGame.Main.test(Main.java:117)
at aStringGame.Main.main(Main.java:137)

這有什么問題?

某處某處正在修改dict 我懷疑它可能會在這個電話中發生:

int value2 = checkLevel(removeWord(bigWord, str, i), dict, passin);
                                                     ^^^^

編輯基本上,會發生的事情是對checkLevel()的遞歸調用通過另一個迭代器修改dict 這使得外部迭代器的快速失敗行為成為可能。

在使用迭代器迭代它時,您無法修改集合。

您嘗試調用iter.remove()會破壞此規則(也可能是您的removeWord方法)。

如果你使用,你可以修改列表,而迭代的ListIterator迭代。

您可以將Set轉換為List並使用List迭代器:

List<String> tempList = new ArrayList<String>(dict);
ListIterator li = tempList.listIterator();

另一種選擇是在迭代時跟蹤要刪除的元素。

例如,您可以將它們放在Set中。

然后,您可以在循環后調用dict.removeAll()

例:

Set<String> removeSet = new HashSet<String>();
for (String s : dict) {
    if (shouldRemove(s)) {
        removeSet.add(s);
    }
}
dict.removeAll(removeSet);

for each循環使用a時for each不允許修改在循環內迭代的Collection 如果需要修改它,請使用經典的for循環

這在所有Collections類中都很常見。 例如,TreeSet中的條目使用failfast方法。

這個類的迭代器方法返回的迭代器是快速失敗的:如果在創建迭代器之后的任何時候修改了set,​​除了通過迭代器自己的remove方法之外,迭代器將拋出ConcurrentModificationException。 因此,在並發修改的情況下,迭代器快速而干凈地失敗,而不是在未來的未確定時間冒着任意的,非確定性行為的風險。

http://docs.oracle.com/javase/6/docs/api/java/util/TreeSet.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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