Java
HashMap
Iteration
Key Removal
Programming Tips

How to remove a key from HashMap while iterating over it?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

If you remove entries from a HashMap by calling map.remove(key) while iterating with a normal loop, Java will usually throw ConcurrentModificationException. The safe rule is simple: if you are iterating with an Iterator, remove through that same iterator. In modern Java, removeIf on the entry set is also a clean option for predicate-based removal.

Why map.remove(...) Fails During Iteration

A HashMap iterator is fail-fast. It keeps track of structural modifications to the map. If the map changes unexpectedly while the iterator is still in use, the iterator detects the mismatch and throws.

That is why this pattern is unsafe:

java
1for (Map.Entry<String, Integer> entry : map.entrySet()) {
2    if (entry.getKey().startsWith("tmp")) {
3        map.remove(entry.getKey());
4    }
5}

The enhanced for loop is using an iterator behind the scenes. Calling map.remove changes the map outside the iterator's own removal path.

The Correct Classic Solution: Iterator.remove()

Use an explicit iterator and remove through it.

java
1import java.util.HashMap;
2import java.util.Iterator;
3import java.util.Map;
4
5public class Main {
6    public static void main(String[] args) {
7        Map<String, Integer> map = new HashMap<>();
8        map.put("keep", 1);
9        map.put("tmpA", 2);
10        map.put("tmpB", 3);
11
12        Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator();
13        while (it.hasNext()) {
14            Map.Entry<String, Integer> entry = it.next();
15            if (entry.getKey().startsWith("tmp")) {
16                it.remove();
17            }
18        }
19
20        System.out.println(map);
21    }
22}

This works because the iterator updates its own internal state when remove() is called.

Two details matter:

  • call next() before remove()
  • call remove() at most once per returned entry

If you violate those rules, you get IllegalStateException.

Java 8 and Later: removeIf

If your logic is a pure filter, removeIf is often cleaner.

java
1import java.util.HashMap;
2import java.util.Map;
3
4public class Main {
5    public static void main(String[] args) {
6        Map<String, Integer> map = new HashMap<>();
7        map.put("keep", 1);
8        map.put("tmpA", 2);
9        map.put("tmpB", 3);
10
11        map.entrySet().removeIf(entry -> entry.getKey().startsWith("tmp"));
12
13        System.out.println(map);
14    }
15}

This is concise and readable, especially when the condition is simple.

When You Need More Control

Sometimes you should not remove during iteration at all. If the removal logic is complicated, or if you need to inspect the map in several passes, collecting keys first can make the code clearer.

java
1import java.util.ArrayList;
2import java.util.HashMap;
3import java.util.List;
4import java.util.Map;
5
6public class Main {
7    public static void main(String[] args) {
8        Map<String, Integer> map = new HashMap<>();
9        map.put("a", 1);
10        map.put("b", 2);
11        map.put("c", 3);
12
13        List<String> keysToRemove = new ArrayList<>();
14        for (Map.Entry<String, Integer> entry : map.entrySet()) {
15            if (entry.getValue() % 2 == 0) {
16                keysToRemove.add(entry.getKey());
17            }
18        }
19
20        for (String key : keysToRemove) {
21            map.remove(key);
22        }
23
24        System.out.println(map);
25    }
26}

This uses extra memory, but it avoids modifying the map during the first traversal.

What About ConcurrentHashMap?

ConcurrentHashMap is for concurrent access, but it does not exist just to avoid learning iterator rules. If your code is single-threaded and the only issue is safe removal during iteration, Iterator.remove or removeIf is still the right answer.

Use ConcurrentHashMap only when you actually need concurrent behavior and understand its iteration semantics.

Common Pitfalls

A common mistake is assuming that removing by key is safe because you are "only deleting the current item". For a fail-fast iterator, that is still an external structural modification.

Another mistake is calling iterator.remove() twice without calling next() again. That triggers IllegalStateException.

People also sometimes choose ConcurrentHashMap to silence the exception instead of fixing the iteration logic.

Finally, if the logic is really filtering, removeIf is clearer than hand-written iterator code in modern Java.

Summary

  • Do not call map.remove(key) while iterating a HashMap with a normal iterator or enhanced for loop
  • The safe classic solution is Iterator.remove() on the iterator you are currently using
  • In Java 8 and later, map.entrySet().removeIf(...) is often the cleanest choice
  • For more complex logic, collect keys first and remove them afterward
  • 'ConcurrentHashMap is not the default fix for single-threaded iteration problems'
  • The key idea is to modify the map in a way the iteration mechanism expects

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.