Back to Blog
Java

Java HashMap remove: Syntax, Return Values, and Pitfalls

java hashmap remove: Learn how to remove entries from a Java HashMap, including return values, iteration safety, and performance tradeoffs.

HashMapJava CollectionsMap RemovalIterationConcurrentModificationException
Illustration of a Java HashMap entry being removed by a key, with a focus on the removal operation.

java hashmap remove requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

The remove method on java.util.HashMap is the standard way to delete an entry by key. It has two overloads: V remove(Object key) and boolean remove(Object key, Object value). The first removes the entry for the given key and returns the previous value, or null if no mapping existed. The second removes the entry only if the key is currently mapped to the specified value, returning true if removal happened.

Understanding the Two remove Overloads

The single-argument overload is the most common. Given a map of user IDs to names, removing a user is straightforward:

Map<Integer, String> users = new HashMap<>(); users.put(1, "Alice"); users.put(2, "Bob"); String removed = users.remove(1); // returns "Alice"

The return value is the value that was associated with the key before removal. If the key was absent, remove returns null. This is useful when you need to know whether a mapping actually existed, but be careful: if the map legitimately contains null values, a null return does not distinguish between "no mapping" and "mapped to null". To check existence before removal, use containsKey or the two-argument overload.

The two-argument overload, added in Java 8, removes the entry only if the key is currently mapped to the given value:

boolean removed = users.remove(2, "Bob"); // true, removes entry boolean notRemoved = users.remove(2, "Alice"); // false, key absent or value mismatch

This overload is atomic: it checks the current mapping and removes it in a single operation. It avoids the race condition that would occur if you called containsKey followed by remove in a concurrent context.

How remove Handles Null Keys and Values

HashMap permits one null key and any number of null values. The remove method handles these without special logic. For a null key, remove(null) will remove the entry if it exists. For values, the two-argument overload uses Objects.equals to compare, so null is handled correctly.

Map<String, String> map = new HashMap<>(); map.put(null, "nullKey"); map.put("key", null); String v1 = map.remove(null); // returns "nullKey" boolean v2 = map.remove("key", null); // true, because value is null

A common mistake is to assume that remove returns null only when the key is absent. If the key was mapped to null, the return value is also null, so you cannot distinguish the two cases without containsKey. The two-argument overload avoids this ambiguity because it returns a boolean.

Removing Entries Safely During Iteration

Iterating over a HashMap while calling remove directly on the map causes a ConcurrentModificationException in most cases. The fail-fast iterator detects structural modification and throws as soon as it advances past the modified element.

// This throws ConcurrentModificationException for (String key : map.keySet()) { if (key.startsWith("temp")) { map.remove(key); } }

To remove entries during iteration, use the iterator's own remove method. The iterator is aware of the modification and updates its internal state correctly.

Iterator<String> it = map.keySet().iterator(); while (it.hasNext()) { String key = it.next(); if (key.startsWith("temp")) { it.remove(); } }

The same pattern works for entrySet() and values(). If you need to remove based on both key and value, use entrySet().iterator() and inspect the Map.Entry.

Java 8 introduced Collection.removeIf, which is a more concise alternative for conditional removal:

map.keySet().removeIf(key -> key.startsWith("temp"));

removeIf internally uses the iterator and is safe from ConcurrentModificationException. It is often the clearest way to express a bulk removal condition.

Performance Characteristics of remove

The average time complexity of remove is O(1), assuming a well-distributed hash function and a load factor below the threshold. The operation computes the key's hash, locates the bucket, and removes the node. In the worst case, when many keys collide into the same bucket, the cost can degrade to O(n) for that bucket, but this is rare with a proper hashCode implementation.

Removing an entry does not shrink the underlying array immediately. The map keeps its capacity and may rehash later if the size drops significantly. If you plan to remove a large number of entries and then keep the map small, consider calling trimToSize? No such method exists on HashMap. Instead, you can create a new map with the remaining entries if memory footprint is a concern.

When using the two-argument overload, the lookup is the same O(1), but it also compares the current value with the given value using Objects.equals. That comparison is usually cheap, but if the value type has an expensive equals method, the removal operation becomes proportionally slower.

Comparing remove, clear, and removeIf

clear() removes all entries in one call. It is O(n) because it must null out every bucket reference, but it is far more efficient than calling remove in a loop for every key. Use clear when you want to reset the map entirely.

removeIf is best for conditional bulk removal based on a predicate. It is implemented as a default method on Collection and works on the key set, value collection, or entry set. It is more readable than an explicit iterator loop and avoids the risk of ConcurrentModificationException.

The single-key remove is the right choice when you know exactly which key to delete. It is simple, fast, and returns the previous value if you need it. The two-argument overload is useful when you want to ensure that you are removing the expected mapping, especially in concurrent or multi-threaded scenarios where a key might have been reassigned.

MethodScopeReturn TypeUse Case
remove(key)Single entryVDelete by key, get previous value
remove(k, v)Single entrybooleanDelete only if key maps to specific value
removeIf(...)MultiplebooleanDelete entries matching a condition
clear()All entriesvoidReset the map entirely

Common Pitfalls with Mutable Keys

If a key object's hashCode changes after it is inserted into the map, the entry will be stored in the wrong bucket. Calling remove with that key will likely fail because the lookup uses the current hash to find the bucket, which no longer matches the bucket where the entry lives. The entry becomes unreachable and effectively leaks memory.

class MutableKey { int id; // hashCode based on id } MutableKey key = new MutableKey(1); map.put(key, "value"); key.id = 2; // hashCode changes map.remove(key); // may not find the entry

To avoid this, use immutable keys or never modify fields that contribute to hashCode after insertion. If you must mutate a key, remove it first, then mutate, then reinsert.

Choosing the Right Removal Approach

The decision among remove(key), remove(key, value), removeIf, and clear depends on the exact requirement. Use remove(key) when you have the key and need the previous value. Use remove(key, value) when you need conditional removal to avoid overwriting a newer mapping. Use removeIf for bulk deletion based on a predicate, and clear when you want to empty the map entirely.

For iteration-based removal, always prefer Iterator.remove() or removeIf over direct map.remove() to avoid ConcurrentModificationException. The iterator approach is explicit and works on all Java versions; removeIf is more concise and available since Java 8.

In concurrent environments, none of these methods are thread-safe on a plain HashMap. If multiple threads modify the map, use ConcurrentHashMap, which provides atomic remove operations and weakly consistent iterators. The remove(key, value) overload on ConcurrentHashMap is especially useful for conditional removal without external synchronization.

java hashmap remove: Practical Usage and Code Examples | RYUSLOG DEV