Unlocking Java’s HashMap & ConcurrentHashMap: Deep Dive into JDK 1.7 vs 1.8 Implementations
Explore the inner workings of Java’s HashMap and ConcurrentHashMap across JDK 1.7 and 1.8, examining their data structures, key methods like put and get, performance optimizations such as treeification, concurrency mechanisms, and practical insights for developers aiming to master these core collections.
Preface
Map-like key‑value structures are classic in software development for in‑memory data storage. Before discussing the concurrent container ConcurrentHashMap , it is essential to understand HashMap , as the former builds upon it.
HashMap
Base 1.7
In JDK 1.7 the internal structure is an array plus linked list. Key member variables include initial bucket size, maximum bucket size, default load factor (0.75), the table array that stores data, map size, and bucket size.
Load factor determines when the map expands: with default capacity 16 and load factor 0.75, expansion occurs after 12 entries, triggering rehash and data copy, which is costly. Pre‑estimating map size can reduce expansion overhead.
The actual storage array is declared as:
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;Each Entry holds key, value, hash, and next (for the linked list).
put method
public V put(K key, V value) { ... }Check if the table needs initialization.
If key is null, delegate to putForNullKey.
Compute hash, locate bucket, traverse linked list to find matching key, replace value if found.
If bucket is empty, create a new Entry.
After insertion, check if resizing is needed.
get method
public V get(Object key) { ... }Compute hash, locate bucket.
If bucket is empty, return null.
Check first node; if it matches, return its value.
If the bucket is a tree, use tree lookup; otherwise traverse the linked list.
In JDK 1.8 the structure is similar but introduces TREEIFY_THRESHOLD to convert long chains into red‑black trees, improving lookup from O(N) to O(log N).
Base 1.8
Key differences: TREEIFY_THRESHOLD determines when a bucket becomes a tree.
Internal class renamed from HashEntry to Node.
The core methods put and get follow the same logical steps, with the added tree conversion for large buckets.
ConcurrentHashMap
ConcurrentHashMap also has 1.7 and 1.8 versions. Both use segment‑based locking (1.7) or CAS plus synchronized (1.8) to achieve thread safety.
Base 1.7
Structure consists of a Segment[] array, each Segment extending ReentrantLock. Inside each segment is a volatile HashEntry<K,V>[] table, count, modCount, threshold, and load factor.
Operations locate the appropriate segment, then lock it before performing put or get. The put method acquires the segment lock, checks for existing keys, updates or inserts entries, and may trigger resizing.
put method (1.7)
public V put(K key, V value) { ... }Steps:
Validate value is not null.
Compute hash and segment index.
Ensure the segment exists.
Delegate to Segment.put, which locks the segment and inserts or updates the entry.
get method (1.7)
public V get(Object key) { ... }Locates the segment, then reads the volatile table without locking, traversing the bucket’s linked list or tree to find the value.
Base 1.8
JDK 1.8 removes the segment concept, using a single volatile Node<K,V>[] table. Concurrency is achieved with CAS for fast paths and synchronized blocks for updates.
put method (1.8)
public V put(K key, V value) { ... }Compute hash.
Initialize table if necessary.
Locate bucket; if empty, attempt CAS to insert a new node.
If the bucket contains a moved marker, trigger resizing.
If a node exists, synchronize on the bucket, insert or update, and treeify if size exceeds TREEIFY_THRESHOLD.
get method (1.8)
public V get(Object key) { ... }Computes hash, locates the bucket, and then:
If the first node matches, return its value.
If the bucket is a tree, perform tree lookup.
Otherwise traverse the linked list.
All reads are lock‑free because the node’s value field is volatile, guaranteeing visibility.
Summary
Both HashMap and ConcurrentHashMap evolved from JDK 1.7 to 1.8. HashMap introduced treeification to improve lookup performance, while ConcurrentHashMap shifted from segment locks to CAS and synchronized, leveraging the same treeification technique for scalability. Understanding these implementations helps developers answer interview questions and write efficient, thread‑safe code.
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.
