Avoid These Common Java Map Pitfalls: Nulls, Custom Keys, and Concurrency Issues
This article explains why some Map implementations reject null values, how using custom objects as keys can cause unexpected behavior, and why ConcurrentHashMap does not guarantee thread safety for compound operations, offering practical guidelines to prevent these frequent Java collection bugs.
In the previous "List pitfalls" article we discussed common mistakes with List; this piece focuses on similar pitfalls that appear when using Map collections in Java.
Not All Maps Allow Null Values
During an internship a simple business code read configuration from XML and stored it in a Map. A later change replaced HashMap with ConcurrentHashMap to avoid potential deadlocks, but the application crashed on startup with an NPE because a null value was inserted into ConcurrentHashMap, which does not permit nulls.
The log showed that a null element from the XML was put into the ConcurrentHashMap, triggering the exception. Unlike HashMap, which accepts null values, ConcurrentHashMap rejects them, a design choice explained by Doug Lea, who called null a "hidden bomb". Josh Bloch, the author of HashMap, had a different view, leading to the divergent null‑handling policies.
Below is a summary of common Map implementations and their support for null keys/values:
Using Custom Objects as Keys
When a custom Goods class is used as a key, failing to override hashCode and equals leads to duplicate entries and inability to retrieve values after the object's fields change.
The HashMap#put implementation first computes the hash code, then checks equality. If the custom object inherits Object#hashCode, each instance gets a distinct hash based on its memory address, causing unexpected behavior.
Based on JDK 1.7 source code.
Therefore, when using custom objects as Map keys, you must override both hashCode and equals and ensure the key is immutable. Lombok’s @EqualsAndHashCode can generate these methods automatically.
Misusing ConcurrentHashMap Can Still Be Thread‑Unsafe
Although ConcurrentHashMap is thread‑safe for single operations, compound actions like get followed by put are not atomic. In a test, expecting a final value of 1001 often yielded a smaller number because two threads interleaved between the read and the increment.
The solution is to synchronize the combined operation or use an AtomicInteger for the counter.
Map Views Share the Underlying Data – Same Pitfalls as List
The keySet, values, and entrySet methods return views backed by the original map. Modifications to the map are reflected in these collections, and they do not support structural modifications like add, though clear and remove are allowed.
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K,V>> entrySet();When exposing these collections to external callers, wrap them in a new collection, e.g., new ArrayList<>(map.values()), to avoid unintended side effects. new ArrayList<>(map.values()); Iterating over a map with foreach while adding or removing elements can also throw ConcurrentModificationException, just like with List.
Summary
Null values can cause ambiguity; proactively check for null before inserting into a map.
Doug Lea advises avoiding null entirely in concurrent maps.
When using custom objects as keys, always override hashCode and equals and keep the key immutable. ConcurrentHashMap is thread‑safe for single operations but not for compound actions; use locking or AtomicInteger when needed.
Map view collections reflect changes to the original map; wrap them in new collections before exposing.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
