簡體   English   中英

如何在沒有ConcurrentModificationException的情況下刪除哈希圖中的多個映射?

[英]How to remove multiple mappings in hashmap without ConcurrentModificationException?

我有2個哈希圖: HashMap<String, Word> hmSmall, hmBig 每個中的映射都是多對一的 因此,基於某些標准,我必須刪除兩個哈希圖中對應於特定值的所有映射。 為此,我正在關注這個答案。

問題是,在哈希表上進行迭代時,我仍然會收到ConcurrentModificationException

這是代碼:

for (Iterator<Word> it = hmSmall.values().iterator(); it.hasNext(); i++) {
            Word value = it.next();//java.util.ConcurrentModificationException here
            String key = value.getKey();
            if (hmBig.containsKey(key)) {
                // if big contains less then remove from big
                // else it.remove

                if (hmBig.get(key).getTotalOccurances() < value
                        .getTotalOccurances()) {

                    hmBig.values().removeAll(
                            Collections.singleton(hmBig.get(key)));

                } else {

                    // it.remove(); not using this based on https://stackoverflow.com/a/30214164/848377
                    hmSmall.values().removeAll(Collections.singleton(value));

                }

            }
        }

有簡單的出路嗎?

Iterator.remove()必須通過Iterator.remove()刪除,以避免ConcurrentModificationException

您的問題是,當您使用Iterator類遍歷HashMap時,您正在通過刪除元素來更改HashMap的大小...

您可以將要刪除的對象存儲在單獨的集中,然后在循環之后刪除所有對象。

比較下面這個stackoverflow帖子中的示例:

Map<String, String> map = new HashMap<>();
map.put("a", "");
map.put("b", "");
map.put("c", "");

Set<String> set = new HashSet<> ();
set.add("a");
set.add("b");

map.keySet().removeAll(set);

System.out.println(map); //only contains "c"

只需將removeAll調用放在循環外即可:

   public static void main(String[] args) {
    // The test map
    final Map<String, String> map = new HashMap<String, String>();
    map.put("Key1", "Value");
    map.put("Key2", "Value");
    map.put("Key3", "Value");

    .


    // Print the map to confirm it worked.
    for(final String key : map.keySet()) {
        map.values().removeAll(Collections.singleton("Value"));
       System.out.println(key + " = " + map.get(key));
    }
}

前一個會導致異常( ConcurrentModificationException ),請嘗試以下操作:

 public static void main(String[] args) {
    // The test map
    final Map<String, String> map = new HashMap<String, String>();
    map.put("Key1", "Value");
    map.put("Key2", "Value");
    map.put("Key3", "Value");


    map.values().removeAll(Collections.singleton("Value"));


    for(final String key : map.keySet()) {
       System.out.println(key + " = " + map.get(key));
    }
}

現在工作正常

正如@Ejp所建議的那樣, Iterator#remove()是擺脫ConcurrentModificationException的最佳解決方案。

此處類似的帖子遍歷Collection,避免在循環中刪除時避免ConcurrentModificationException

同樣在java8中,您可以很好地使用removeIf()方法。 一遍遍Collection,避免在循環中刪除時避免ConcurrentModificationException

因此,此處的重點是不要在迭代時更改哈希圖的大小。 因此,我沒有在循環中刪除條目,而是在數組列表中添加了鍵。 當循環結束時,我遍歷了該數組列表並刪除了與該數組列表中的鍵相對應的哈希映射的條目。

這是代碼:

ArrayList<String> alsmallhm=new ArrayList<String>();
        for (Iterator<Word> it = hmSmall.values().iterator(); it.hasNext(); i++) {
            Word value = it.next();//java.util.ConcurrentModificationException here
            String key = value.getKey();
            if (hmBig.containsKey(key)) {
                // if big contains less then remove from big
                // else it.remove

                if (hmBig.get(key).getTotalOccurances() < value
                        .getTotalOccurances()) {

                    hmBig.values().removeAll(
                            Collections.singleton(hmBig.get(key)));

                } else {

                    // it.remove();
                    alsmallhm.add(key);
                    /*hmSmall.values().removeAll(Collections.singleton(value));*/

                }

            }
        }

        for(String s:alsmallhm){
            hmSmall.values().removeAll(Collections.singleton(hmSmall.get(s)));
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM