编译错误ConcurrentModificationException,尝试使用方法删除相同的名称

时间:2014-02-22 09:56:27

标签: java hashmap static-methods

我试图让removeItemFromMapByValue方法与removeItemFromMapByValue一起工作,但是当我开始编译代码时,我得到 ConcurrentModificationException removeItemFromMapByValue必须删除值中的相同名称。

    public class Solution
        {
            public static HashMap<String, String> createMap()
            {
                HashMap<String, String> map = new HashMap<String, String>();
                map.put("Stallone", "Silvest");
                map.put("Morikone", "Enio");
                map.put("Vivaldi","Antonio");
                map.put("Belucci", "Monica");
                map.put("Gudini", "Harry");
                map.put("Verdo", "Dhuzeppe");
                map.put("Maracci", "Bruno");
                map.put("Carleone", "Vito");
                map.put("Bracco", "Luka");
                map.put("Stradivari", "Antonio");
                return map;
            }
            public static void removeTheFirstNameDuplicates(HashMap<String, String> map)
            {
                for (Map.Entry<String, String> pair : map.entrySet()){
                    String name = pair.getValue();
                    removeItemFromMapByValue(map, name);
                }
            }
            public static void removeItemFromMapByValue(HashMap<String, String> map, String value)
            {
                HashMap<String, String> copy = new HashMap<String, String>(map);
                for (Map.Entry<String, String> pair: copy.entrySet())
                {
                    if (pair.getValue().equals(value))
                        map.remove(pair.getKey());
                }
            }
            public static void main(String[] args)
            {
                HashMap<String, String> map = createMap();
                removeTheFirstNameDuplicates(map);
                System.out.println(map);
            }
        }

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:926)
    at java.util.HashMap$EntryIterator.next(HashMap.java:966)
    at java.util.HashMap$EntryIterator.next(HashMap.java:964)
    at com.javarush.test.level08.lesson08.task05.Solution.removeTheFirstNameDuplicates(Solution.java:32)
    at com.javarush.test.level08.lesson08.task05.Solution.main(Solution.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

Process finished with exit code 1

2 个答案:

答案 0 :(得分:3)

<强>这里:

        for (Map.Entry<String, String> pair : map.entrySet()){
            String name = pair.getValue();
            removeItemFromMapByValue(map, name); //you are about to delete a map item here!
        }

您正在修改您当前循环的集合==&gt; ConcurrentModificationException

答案 1 :(得分:3)

简单的解决方案是修复第一种方法,因为这样可以避免错误并且行为正确。

// remove any duplicated values, leaving one entry.
public static void removeTheFirstNameDuplicates(HashMap<String, String> map) {
     Map<K,V> map2 = invert(invert(map));
     map.clear();
     map.putAll(map2);
}

public static <K, V> Map<V, K> invert(Map<K, V> map) {
     Map<V, K> map2 = new HashMap<>();
     for(Map.Entry<K< V> entry: map.entrySet())
         map2.put(entry.getValue(), entry.getKey());
     return map2;
}

您的编译器不会产生ConcurrentModifcationException。您应该查看堆栈轨道中的行,以便在迭代时查看修改集合的位置,例如。

for (Map.Entry<String, String> pair: copy.entrySet())
{
    if (pair.getValue().equals(value))
        map.remove(pair.getKey());
}

在这种情况下,您将在迭代时删除条目。一个简单的解决方案是直接使用Iterator。通常,IDE可以执行此重构。

for (Iterator<String> iter = copy.values().iterator(); iter.hasNext();) {
    if (iter.next().equals(value))
        iter.remove();
}

此解决方案的问题是从嵌套中调用它,它将删除所有匹配条目,就像在代码中一样。即它将删除所有条目。