问题描述:

I have 2 hashmaps: HashMap<String, Word> hmSmall, hmBig. The mapping in each is many-to-one. Hence based on some criteria, I have to remove all the mappings corresponding to a particular value in both hashmaps. And for that, I am following this answer.

The problem is that I still get ConcurrentModificationException while iterating over the hashmap.

Here is the code:

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 http://stackoverflow.com/a/30214164/848377

hmSmall.values().removeAll(Collections.singleton(value));

}

}

}

Is there simple way out?

网友答案:

You have to remove via Iterator.remove() while you're iterating to avoid ConcurrentModificationException.

网友答案:

Your Problem is, that, while you iterate through your HashMap with the Iterator Class, you are changing the size of the HashMap by removing elements...

You can store the objects to be removed in a separate set and then remove all after the loop.

Compare the example from this stackoverflow post:

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"
网友答案:

Just put the removeAll call outside the loop:

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

the previous will cause exception (ConcurrentModificationException) try this:

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

Now it works fine

网友答案:

As @Ejp suggested , Iterator#remove() is the optimal solution to get rid of ConcurrentModificationException.

A similar kind of post here Iterating through a list, avoiding ConcurrentModificationException when removing in loop.

Also with java8 , you can very well use removeIf() method . Have a look at Iterating through a list, avoiding ConcurrentModificationException when removing in loop

网友答案:

So the key point here is not to change the size of the hashmap while iterating. Thus instead of deleting the entry within the loop, I added the key in an arraylist. And when the loop got over, I traversed through that arraylist and deleted the entries of the hashmap corresponding to the key in the arraylist.

Here is the code:

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)));
        }
相关阅读:
Top