2014-02-22 20 views
1

我試着讓我的removeItemFromMapByValue方法工作,removeItemFromMapByValue在一起,但是當我開始收集我的代碼我得到ConcurrentModificationException的removeItemFromMapByValue必須在值中刪除相同的名稱。請編譯錯誤ConcurrentModificationException的,試圖使用方法去除相同的名稱

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 
+0

你確定當**編譯**時會出現'ConcurrentModificationException'錯誤嗎?如果它實際上是運行時錯誤,您可以發佈確切的錯誤消息或堆棧跟蹤嗎? –

+1

1)它不是編譯錯誤。這是運行程序時引發的異常。 2)如果你得到一個異常,你應該如何處理異常棧跟蹤。 –

+0

你混淆了編譯錯誤和運行時異常。如果您收到編譯錯誤,那麼您的問題應該包含來自編譯器的確切且完整的錯誤消息。如果你得到一個運行時異常,你的問題應該包含異常的完整堆棧跟蹤。閱讀錯誤信息是瞭解發生什麼和在哪裏發生的最佳方式。不讀它會讓你和我們猜測問題可能是什麼。 –

回答

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(); 
} 

這個解決方案的問題是,這是從嵌套調用,因爲它在你的代碼確實它會刪除所有匹配的條目。即它將刪除所有條目。

+0

抱歉,我沒有得到它=( –

+0

@Predict_it你在迭代集合的時候修改集合,這就是爲什麼你會得到一個併發修改異常,你的第一個循環迭代所有的值,第二個循環刪除所有匹配的值那麼,如果你沒有得到這個錯誤,你會刪除所有元素。 –

+0

它仍然沒有刪除相同的名稱,只有其中一個不見了vivaldi = antonio –

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! 
     } 

您正在修改你是目前通過==循環>ConcurrentModificationException

+1

事實上,如果他真的想刪除該循環中的項目,他需要使用迭代器。 – Aaron

+0

@Aaron不幸的是這個方法在一個循環中被調用,所以它更復雜一點;) –

+0

@PeterLawrey,@Predict_it如果你喜歡你可以使用一個臨時集合'loopSet'並且你將'map.entrySet'項目複製到它並使用如果您的循環作爲替代_quick&dirty_fix。 – donfuxx

相關問題