Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iterating over and removing from a map [duplicate]

Tags:

java

People also ask

How do you delete a map while iterating?

You should always use Iterator's remove() method to remove any mapping from the map while iterating over it to avoid any error. Use of Map. remove() method is prohibited during traversal because it throws ConcurrentMdoficiationException.

Can we remove element from HashMap while iterating?

While iterating, check for the key at that iteration to be equal to the key specified. The entry key of the Map can be obtained with the help of entry. getKey() method. If the key matches, remove the entry of that iteration from the HashMap using remove() method.

Can we add a new entry to HashMap while iterating?

How to add new entry while iterating? Create a new Map<String, String> foo instance and set the desired values there. At the end of your process, assign this map to your old map by using map = foo; .

Can we update HashMap while iterating?

Well, you can't do it by iterating over the set of values in the Map (as you are doing now), because if you do that then you have no reference to the keys, and if you have no reference to the keys, then you can't update the entries in the map, because you have no way of finding out which key was associated with the ...


Here is a code sample to use the iterator in a for loop to remove the entry.

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

As of Java 8 you could do this as follows:

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

Oracle Docs: entrySet()

The set is backed by the map, so changes to the map are reflected in the set, and vice-versa


Use a real iterator.

Iterator<Object> it = map.keySet().iterator();

while (it.hasNext())
{
  it.next();
  if (something)
    it.remove();
 }

Actually, you might need to iterate over the entrySet() instead of the keySet() to make that work.


is there a better solution?

Well, there is, definitely, a better way to do so in a single statement, but that depends on the condition based on which elements are removed.

For eg: remove all those elements where value is test, then use below:

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

UPDATE It can be done in a single line using Lambda expression in Java 8.

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

I know this question is way too old, but there isn't any harm in updating the better way to do the things :)


ConcurrentHashMap

You can use java.util.concurrent.ConcurrentHashMap.

It implements ConcurrentMap (which extends the Map interface).

E.g.:

Map<Object, Content> map = new ConcurrentHashMap<Object, Content>();

for (Object key : map.keySet()) {
    if (something) {
        map.remove(key);
    }
}

This approach leaves your code untouched. Only the map type differs.


Java 8 support a more declarative approach to iteration, in that we specify the result we want rather than how to compute it. Benefits of the new approach are that it can be more readable, less error prone.

public static void mapRemove() {

    Map<Integer, String> map = new HashMap<Integer, String>() {
        {
            put(1, "one");
            put(2, "two");
            put(3, "three");
        }
    };

    map.forEach( (key, value) -> { 
        System.out.println( "Key: " + key + "\t" + " Value: " + value );  
    }); 

    map.keySet().removeIf(e->(e>2)); // <-- remove here

    System.out.println("After removing element");

    map.forEach( (key, value) -> { 
        System.out.println( "Key: " + key + "\t" + " Value: " + value ); 
    });
}

And result is as follows:

Key: 1   Value: one
Key: 2   Value: two
Key: 3   Value: three
After removing element
Key: 1   Value: one
Key: 2   Value: two