简体   繁体   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;
}

Error: 错误:

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)

What's the problem here? 这有什么问题?

Something somewhere is modifying dict . 某处某处正在修改dict I suspect it might be happening inside this call: 我怀疑它可能会在这个电话中发生:

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

edit Basically, what happens is that the recursive call to checkLevel() modifies dict through another iterator. 编辑基本上,会发生的事情是对checkLevel()的递归调用通过另一个迭代器修改dict This makes the outer iterator's fail-fast behaviour to kick in. 这使得外部迭代器的快速失败行为成为可能。

You can't modify a Collection while you're iterating over it with an Iterator. 在使用迭代器迭代它时,您无法修改集合。

Your attempt to call iter.remove() breaks this rule (your removeWord method might, too). 您尝试调用iter.remove()会破坏此规则(也可能是您的removeWord方法)。

You CAN modify a List while iterating IF you use a ListIterator to iterate. 如果你使用,你可以修改列表,而迭代的ListIterator迭代。

You can convert your Set to a List and use a List iterator: 您可以将Set转换为List并使用List迭代器:

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

Another option is to keep track of the elements you want to remove while iterating. 另一种选择是在迭代时跟踪要删除的元素。

You could place them in a Set, for example. 例如,您可以将它们放在Set中。

You could then call dict.removeAll() after your loop. 然后,您可以在循环后调用dict.removeAll()

Example: 例:

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

When using a for each loop you are not allowed to modify the Collection you are iterating inside the loop. for each循环使用a时for each不允许修改在循环内迭代的Collection If you need to modify it, use a classic for loop 如果需要修改它,请使用经典的for循环

This is a common occurance in all Collections classes. 这在所有Collections类中都很常见。 For instance the entry in TreeSet uses failfast method. 例如,TreeSet中的条目使用failfast方法。

The iterators returned by this class's iterator method are fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. 这个类的迭代器方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候修改了set,​​除了通过迭代器自己的remove方法之外,迭代器将抛出ConcurrentModificationException。 Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future. 因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒着任意的,非确定性行为的风险。

http://docs.oracle.com/javase/6/docs/api/java/util/TreeSet.html 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