1. Overview
In this article, we'll discuss different ways to remove an entry from a Java HashMap.
2. Introduction
HashMap stores entries in (Key, Value) pairs with unique keys. Thus, one idea would be to use the key as an identifier to remove an associated entry from the map.
We can use the methods provided by the java.util.Map interface for entry removal using the key as an input.
2.1. Using Method remove(Object key)
Let's try it out using a simple example. We've got a map that associates food items with food types:
HashMap<String, String> foodItemTypeMap = new HashMap<>();
foodItemTypeMap.put("Apple", "Fruit");
foodItemTypeMap.put("Grape", "Fruit");
foodItemTypeMap.put("Mango", "Fruit");
foodItemTypeMap.put("Carrot", "Vegetable");
foodItemTypeMap.put("Potato", "Vegetable");
foodItemTypeMap.put("Spinach", "Vegetable");
Let's remove the entry with the key “Apple”:
foodItemTypeMap.remove("Apple");
// Current Map Status: {Potato=Vegetable, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Spinach=Vegetable}
2.2. Using Method remove(Object key, Object value)
This is a variant of the first method and accepts both key and value as inputs. We use this method in case we want to delete an entry only if a key is mapped to a specific value.
In foodItemTypeMap, the key “Grape” is not mapped with the “Vegetable” value.
As a result, the below operation won't lead to any updates:
foodItemTypeMap.remove("Grape", "Vegetable");
// Current Map Status: {Potato=Vegetable, Carrot=Vegetable, Grape=Fruit, Mango=Fruit, Spinach=Vegetable}
Now, let's explore other scenarios of entry removal in a HashMap.
3. Removing an Entry While Iterating
The HashMap class is unsynchronized. If we try to add or delete an entry concurrently, it might result in ConcurrentModificationException. Therefore, we need to synchronize the remove operation externally.
3.1. Synchronizing on External Object
One approach is to synchronize on an object that encapsulates the HashMap. For example, we can use the entrySet() method of the java.util.Map interface to fetch a Set of entries in a HashMap. The returned Set is backed by the associated Map.
Thus, any structural modification of the Set would result in an update to the Map as well.
Let's remove an entry from the foodItemTypeMap using this approach:
Iterator<Entry<String, String>> iterator = foodItemTypeMap.entrySet().iterator();
while (iterator.hasNext()) {
if (iterator.next().getKey().equals("Carrot"))
iterator.remove();
}
Structural modifications on the map might not be supported unless we're using the iterator's own methods for an update. As we can see in the above snippet, we're invoking the remove() method on the iterator object instead of the map. This provides a thread-safe removal operation.
We can achieve the same result in Java 8 or later using the removeIf operation:
foodItemTypeMap.entrySet()
.removeIf(entry -> entry.getKey().equals("Grape"));
3.2. Using ConcurrentHashMap<K, V>
The java.util.concurrent.ConcurrentHashMap class provides thread-safe operations. Iterators for ConcurrentHashMap use only one thread at a time. Hence, they enable deterministic behavior for concurrent operations.
We can specify the number of concurrent thread operations permitted using ConcurrencyLevel.
Let's use the basic remove method for removing entries in a ConcurrentHashMap:
ConcurrentHashMap<String, String> foodItemTypeConcMap = new ConcurrentHashMap<>();
foodItemTypeConcMap.put("Apple", "Fruit");
foodItemTypeConcMap.put("Carrot", "Vegetable");
foodItemTypeConcMap.put("Potato", "Vegetable");
for (Entry<String, String> item : foodItemTypeConcMap.entrySet()) {
if (item.getKey() != null && item.getKey().equals("Potato")) {
foodItemTypeConcMap.remove(item.getKey());
}
}
4. Conclusion
We have explored different scenarios of entry removal in a Java HashMap. If not iterating, we can use the standard entry removal methods provided by the java.util.Map interface safely.
In case we're updating the Map during iteration, it's imperative to use remove methods on an encapsulating object. Additionally, we analyzed an alternative class, ConcurrentHashMap, that enables thread-safe update operations on Map.