2012-12-18 99 views
7

我打電話函數返回TreeMap實例,而在調用代碼中我想修改TreeMap。但是,我得到ConcurrentModificationException避免TreeMap ConcurrentModificationException?

這裏是我的代碼:

public Map<String, String> function1() { 
    Map<String, String> key_values = Collections.synchronizedMap(new TreeMap<String, String>()); 
    // all key_values.put() goes here 

    return key_values; 
} 

而且我調用的代碼是:

Map<String, String> key_values =Collections.synchronizedMap(Classname.function1()); 
//here key_values.put() giving ConcurrentModificationException 
+1

我可以問一下從function1內創建一個同步映射嗎?它不被任何人使用,除了你的「呼叫代碼」... –

+0

你如何修改地圖? –

回答

2

如果您使用ConcurrentSkipListMap是可以更快,並沒有這個問題。

public NavigableMap<String, String> function1() { 
    NavigableMap<String, String> key_values = new ConcurrentSkipListMap<String, String>(); 
    // all key_values.put() goes here 

    return key_values; 
} 

如果你不需要排序鍵,你可以使用ConcurrentHashMap

+1

瞭解*跳過列表*的含義可能很有用:https://en.wikipedia.org/wiki/Skip_list –

13

請注意,如果您使用的是迭代器Collections.synchronizedMap永遠保護你免受併發修改。另外,除非您從多個線程訪問您的Map,否則創建同步映射是無用的。 未交給其他線程的局部範圍集合和變量不需要爲​​。

我的猜測是,在你離開了代碼,你遍歷的Map.entrySet一個,Map.keySet,或Map.values,並且在該迭代(在for環路內)調用put。用你所顯示的代碼,這是唯一可能發生的事情。

+0

你好,你寫先生,那是我的錯誤..謝謝 –

1

您似乎正在獲取同步映射的同步映射。如果我更換呼叫功能1()用它的內容(簡體),我們有:

Map<String, String> key_values =Collections.synchronizedMap(Collections.synchronizedMap(new TreeMap<String, String>())); 

我覺得你的電話線應改爲:

Map<String, String> key_values = Classname.function1(); 
+1

不是一個真正的答案,所以沒有+1,但仍然是一個很好的音符。 – Brian

+0

@布萊恩我覺得這個細節很重要。因爲,使用這個雙重包裝,他將無法在實際的TreeMap對象上同步,如果他嘗試迭代和更新,他將需要它。 –

1

你正在尋找一個同步的Map ,所以我假設你正在處理一個多線程的應用程序。在這種情況下,如果您想使用迭代器,則必須爲MAP同步塊。

/*This reference will give error if you update the map after synchronizing values.*/ 
    Map<String, String> values =Collections.synchronizedMap(function1()); 

/*This reference will not give error if you update the map after synchronizing values */ 
     Map<String, String> values = Collections.synchronizedMap(new TreeMap<String, String>()); 


    synchronized (values) 
       {   
        Iterator it = values.entrySet().iterator(); 
        while(it.hasNext()) 
        { 
         it.next() ; 
    // You can update the map here.  
        } 
       } 

更新:

其實你的情況,考慮您兩次包裹MAP的犯錯,即使有一個synchronized塊修改它while循環會給CM異常,你會無法在正在獲取udpated的原始MAP對象上同步。