1

我有一個HashMap,其類型HashMap<String,HashMap<String,int>>現在我需要遍歷這個HashMap並刪除任何鍵值爲0的內部HashMap。如何迭代一個HashMap,同時避免ConcurrentModificationException

如果這樣的刪除使內部HashMap爲空,那麼內部HashMap的相應鍵將從外部HashMap中移除。我試着迭代它,然後刪除符合要求的元素,但是這會引發我一個ConcurrentModificationException

我嘗試下面的代碼:

synchronized(MyConstants.cliListUpdateList) 
{ 
    synchronized(MyConstants.cliList) 
    { 
     outerEntries = MyConstants.cliListUpdateList.entrySet(); 
     outerIterator = outerEntries.iterator(); 

     while(outerIterator.hasNext()) 
     { 
      outerEnt = (Entry) outerIterator.next(); 
      innerHashMap = (HashMap) outerEnt.getValue(); 
      synchronized(innerHashMap) 
      {//synchronize innerhashmap 
      innerEntries = innerHashMap.entrySet(); 
      innerIterator = innerEntries.iterator(); 
      synchronized(innerIterator) 
      { 
      while(innerIterator.hasNext()) 
      { 
       innerEnt = (Entry) innerIterator.next(); 
       int k = Integer.parseInt((String)innerEnt.getValue()); 
       if(k==0) 
       { 
        innerHashMap.remove(innerEnt.getKey()); 
        if(innerHashMap.isEmpty()) 
        { 
         MyConstants.cliListUpdateList.remove(outerEnt.getKey()); 
        } 

        ArrayList ports = (ArrayList) MyConstants.cliList.get(outerEnt.getKey()); 
        ports.remove((String)innerEnt.getKey()); 
        if(ports.isEmpty()) 
        { 
         MyConstants.cliList.remove(outerEnt.getKey()); 
        } 
       } 
       else 
       { 
        k--; 
        innerHashMap.put(innerEnt.getKey(), k+""); 
        MyConstants.cliListUpdateList.put(outerEnt.getKey(), innerHashMap); 
       } 

      } 
      } 
     }//synchronize innerhashmap 
     } 


     System.out.println(MyConstants.cliListUpdateList + " <---> "+ MyConstants.cliList); 

    } 
} 

我得到這一行除外:innerEnt = (Entry) innerIterator.next();。我嘗試了Iterator類提供的remove方法。但那也不行。

編輯

從Java文檔,我知道這麼多if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this(ConcurrentModificationException) exception但我需要完全相同的功能。

+0

我嘗試儘可能多的synchronized塊地,但沒有好的:( – sasidhar 2012-03-12 10:17:52

+0

同步贏't救你,因爲這全部是由單個線程引起的。同步用於序列化由多個線程對一個非線程安全的容器執行的操作,例如'HashMap'。來自java docs的 – 2012-03-12 10:43:24

回答

7

可能不能完全而是的innerHashMap.remove(innerEnt.getKey());解決您的問題,您需要使用迭代器的remove方法innerIterator.remove();

+0

嘗試過,但在相同的地方相同的錯誤。沒有改進:( – sasidhar 2012-03-12 10:31:43

+1

準確地說,迭代器被設計爲允許刪除當前的鍵/值對,同時保持迭代器的完整性。'entrySet'的文檔明確指出,通過'remove'刪除是可以接受的。已經改變了所有的刪除使用適當的迭代器? – 2012-03-12 10:32:50

+0

除上述之外,使用'Map.Entry.setValue'而不是'put'來減少內部映射中的計數器。文檔建議使用'put'應該可以,但是試試這個吧 – 2012-03-12 10:42:27

2

你試過使用Synchronized Hashmap嗎? Collections.synchronizedMap(new HashMap())或看看ConcurrentHashMap

+0

我知道這很多'如果一個線程在使用快速迭代器對集合進行迭代時直接修改集合,那麼迭代器將拋出此(ConcurrentModificationExcepti )異常',但我需要完全相同的功能:( – sasidhar 2012-03-12 10:26:25

相關問題