2015-10-01 106 views
-1

我有此HashMap如何從HashMap中刪除密鑰?

HashMap <Integer,Integer> H = new HashMap <Integer,Integer>(); 

,當我嘗試刪除從HashMap中的關鍵我recive這個錯誤

**Exception in thread "main" java.util.ConcurrentModificationException 
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:922) 
at java.util.HashMap$KeyIterator.next(HashMap.java:956) 
at Livre.montantTotal(Livre.java:42)** 

這是我的代碼

for (int e : H.keySet()){ 
    H.put(e, H.get(e)-1); 
    if (H.get(e) == 0){ 
     H.remove(e); 
    } 
} 
+0

您在遍歷整個集合時無法修改集合。 –

+0

好吧,您可以在Iterator上使用remove()方法(因此將for循環展開成適當的Iterator),但是當您迭代它時,您將無法添加到集合中。也許收集列表中的新增內容並在最後添加它們。 – slipperyseal

+0

@FernandoMatsumoto嗯,它是相關的,但並不真正重複,因爲這裏是一張地圖 – Dici

回答

0

你不能改變當你迭代它時有一些東西。當你改變HashMap時,你也改變它keySet,並且由於你正在迭代它,所以Java會拋出一個錯誤。您可能需要做的是將需要移除的每個密鑰添加到單獨的列表中,然後遍歷該列表。

像這樣:

ArrayList<Integer> otherList = new ArrayList<>(); 
for(int e : H.keySet()){ 
    h.put(e, H.get(e) - 1); 
    if(H.get(e) == 0) 
     otherList.add(e); 
} 

for(int e : otherList){ 
    H.remove(e); 
} 
+2

根據文檔,可以使用'Iterator.remove'從集合中刪除項目,並且更改將反映到地圖。我不認爲這是線程安全的,儘管 – Dici

+0

毫無疑問比修改來自多線程的映射更安全。 – slipperyseal

+0

@SlipperySeal true – Dici

3

您需要使用Iterator在遍歷它從集合中刪除。

for (Iterator<Map.Entry<Integer, Integer>> i = H.entrySet().iterator(); i.hasNext();) { 
    Map.Entry<Integer, Integer> e = i.next(); 
    int v = e.getValue(); 
    if (v == 1) 
     i.remove(); 
    else 
     e.setValue(v - 1); 
} 

HashMap.EntrySet()https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html)文檔

set受映射支持,所以對映射的變化反映在 集合,反之亦然。

+0

認爲引用doc以證明更改將反映到地圖是有用的。這不是微不足道的開始 – Dici

+1

@Dici我會盡力找到相關的位。 –

2

由於您嘗試刪除元素並重新排列哈希映射,而哈希映射已在使用中(同時循環),您會收到此錯誤。

要循環遍歷Java中的集合對象,您有一個Iterator類,它可以解決您的問題。該類有一個remove()方法從HashMap中刪除密鑰對值。

How to remove a key from HashMap while iterating over it?可能的複製和
iterating over and removing from a map

編輯:

嘗試在Java 7中的代碼和更早版本:

Map<String, String> map = new HashMap<String, String>() { 
    { 
    put("test", "test123"); 
    put("test2", "test456"); 
    } 
}; 

for(Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); it.hasNext();) { 
    Map.Entry<String, String> entry = it.next(); 
    if(entry.getKey().equals("test")) { 
    it.remove(); 
    } 
} 

在Java 8,你可以試試這個:

map.entrySet().removeIf(e-> <boolean expression>); 
+0

Upvoting,因爲你不能評論,但如果你有足夠的代表,這應該是一個評論。如果您包含完整答案而不僅僅是其他問題的鏈接,那麼它會作出更好的回答 – Dici

+0

Java 8的加入非常棒,因爲這是人們需要了解的Map API最近發生的一些重大變化。值得告訴你改善你的答案,並提高你的表現:) – Dici