Performance of Java Map Implementations
Performance of Java Map Implementations
com/java-map-concepts
JavaMap
The Map interface in Java is a part of the [Link]
package and provides a way to store key-value pairs.
It does not inherit from Collection, and instead
defines a specific set of methods to interact with
the key-value mappings.
1 of 46 02/11/25, 10:21 am
JavaMap [Link]
Interface:
Appearance
Add new Edit this post
1. void clear()
Use Case: To reset the map by removing all key-
value mappings.
2. boolean containsKey(Object key)
Use Case: To check if a specific key is present in
the map.
3. boolean containsValue(Object value)
Use Case: To check if any key in the map is
associated with a given value.
4. Set<[Link]<K, V>> entrySet()
Use Case: To obtain a set view of the map's key-
value pairs, useful for iteration.
5. V get(Object key)
Use Case: To retrieve the value associated with a
specified key.
6. boolean isEmpty()
Use Case: To determine if the map contains no key-
value mappings (i.e., it is empty).
7. Set<K> keySet()
Use Case: To get a set view of the keys in the
map, which can be useful for iterating over the
keys.
8. V put(K key, V value)
Use Case: To add or update a key-value pair in the
map.
9. void putAll(Map<? extends K, ? extends V> m)
Use Case: To copy all mappings from another map to
the current map.
10. V remove(Object key)
Use Case: To remove a key-value pair from the map
by specifying the key.
11. int size()
Use Case: To get the number of key-value pairs in
the map.
12. Collection<V> values()
2 of 46 02/11/25, 10:21 am
JavaMap [Link]
[Link](key, value);
HashMap uses:
@Override
public int hashCode() {
return 100; // Same hash for all Emp objects
}
All Emp objects go to same bucket (because hashCode() is
constant).
@Override
public boolean equals(Object obj) {
return id == [Link] && [Link](name, [Link]);
}
Output:
{Emp [id=101, name=Nitesh]=12345}
3 of 46 02/11/25, 10:21 am
JavaMap [Link]
So:
[Link](new Emp(101, "Nitesh"), 123);
[Link](new Emp(101, "Nitesh"), 12345);
Here:
Output:
4 of 46 02/11/25, 10:21 am
JavaMap [Link]
5 of 46 02/11/25, 10:21 am
JavaMap [Link]
package [Link];
Appearance Add new Edit this post
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
6 of 46 02/11/25, 10:21 am
JavaMap [Link]
[Link]("\nUsing entrySet():");
Appearance Add new Edit this post
Set<Entry<String, Integer>> entries = [Link]();
for (Entry<String, Integer> entry : entries) {
[Link]([Link]() + ": " +
[Link]());
}
// Output:
// Apple: 10
// Banana: 20
// Orange: 30
7 of 46 02/11/25, 10:21 am
JavaMap [Link]
Concepts of Hashtable
1. Thread-Safe by Default:
◦ No need to synchronize externally for thread-
safe operations.
2. No Null Keys/Values:
8 of 46 02/11/25, 10:21 am
JavaMap [Link]
◦ Attempting
Appearance Add new
to insert a null key or value
Edit this post
results in a NullPointerException.
3. Synchronized Operations:
◦ Operations like put, get, and remove are
synchronized. However, this may lead to
performance bottlenecks in high-concurrency
scenarios.
4. Performance Trade-off:
◦ Due to synchronization, Hashtable is slower
than HashMap for single-threaded applications.
5. Key Uniqueness:
◦ Duplicate keys are not allowed; adding a value
with an existing key will overwrite the
previous value.
1. Multi-Threaded Applications:
◦ When a thread-safe map is required without
external synchronization.
◦ Example: Session management in a web
application where multiple threads access a
shared data store.
2. Legacy Systems:
◦ When working with older Java applications that
were designed with Hashtable before
ConcurrentHashMap was introduced.
3. Simple Cache:
◦ Implementing a basic thread-safe cache for
read-write operations.
4. Resource Locking:
◦ Maintaining a mapping of resources to locks for
synchronized access in a multithreaded
application.
9 of 46 02/11/25, 10:21 am
JavaMap [Link]
Load Factor
10 of 46 02/11/25, 10:21 am
JavaMap [Link]
Constructor Variants
Appearance Add new Edit this post
1. Default Constructor:
◦ Creates a Hashtable with an initial capacity of
11 and a load factor of 0.75.
2. Constructor with Initial Capacity:
◦ Allows you to specify the initial capacity. For
example:
▪ Creates a Hashtable with an initial
capacity of 20 buckets.
3. Constructor with Initial Capacity and Load Factor:
◦ Allows you to specify both the initial capacity
and the load factor. For example:
▪ Creates a Hashtable with an initial
capacity of 20 and a load factor of 0.5.
11 of 46 02/11/25, 10:21 am
JavaMap [Link]
• Perform
Appearance
ance Opti
Add new
mization:
Edit this post
◦ To minimize the cost of resizing (rehashing),
set an initial capacity large enough to
accommodate the expected number of entries.
• Reduce Memory Waste:
◦ Avoid allocating excessive memory for small
datasets.
import [Link];
// Retrieve value
[Link]("Value for 'Apple': " +
[Link]("Apple")); // Output: 10
12 of 46 02/11/25, 10:21 am
JavaMap [Link]
Advantages
Disadvantages
package [Link];
13 of 46 02/11/25, 10:21 am
JavaMap [Link]
import [Link];
Appearance Add new Edit this post
public class Demo03HashMap {
// Removing an entry
[Link]("Banana");
[Link]("After removing Banana: " + map);
}
}
Step 1: Initialization
• Initial Capacity: The HashMap is initialized with
an initial capacity of 4. It means that it will
start with 4 buckets.
• Load Factor: The load factor is 0.75, meaning when
75% of the map's capacity is filled, it will
resize. So, after inserting 3 elements, the map
will trigger a resize.
14 of 46 02/11/25, 10:21 am
JavaMap [Link]
computed.
Appearance Add new Edit this post
• Bucket Index Calculation: hashCode("Apple") %
4 determines the bucket where this key-value
pair will go.
• Insertion: Since bucket 1 (index 1) is empty,
"Apple" -> 10 is inserted there.
2. Inserting "Banana" -> 20 :
• Hashing: The hashCode() for "Banana" is
computed.
• Bucket Index Calculation: hashCode("Banana") %
4 determines the bucket index.
• Insertion: The key-value pair "Banana" -> 20
is inserted into bucket 3.
3. Inserting "Cherry" -> 30 :
• Hashing: The hashCode() for "Cherry" is
computed.
• Bucket Index Calculation: hashCode("Cherry") %
4 determines the bucket index.
• Insertion: The key-value pair "Cherry" -> 30
is inserted into an available bucket.
4. Inserting "Date" -> 40 :
• Hashing: The hashCode() for "Date" is
computed.
• Bucket Index Calculation: hashCode("Date") % 4
determines the bucket index.
• Insertion: "Date" -> 40 is inserted into a
bucket.
5. Inserting "Elderberry" -> 50 :
• This operation triggers resizing because the
number of elements in the HashMap exceeds the
load factor threshold (0.75 * 4 = 3).
• Resize Triggered: The capacity of the HashMap
is doubled from 4 to 8. This means the bucket
array size increases to accommodate more
entries.
• Rehashing: After resizing, all the existing
entries are rehashed and redistributed into the
new bucket array.
◦ The keys are placed in different buckets
15 of 46 02/11/25, 10:21 am
JavaMap [Link]
16 of 46 02/11/25, 10:21 am
JavaMap [Link]
follows:
Appearance Add new Edit this post
Next→
17 of 46 02/11/25, 10:21 am
JavaMap [Link]
For example:
Let’s say we have two objects, emp1 and emp2 , that both hash
to the same bucket index. In this case, both emp1 and emp2
18 of 46 02/11/25, 10:21 am
JavaMap [Link]
import [Link];
import [Link];
class Emp {
int id;
String name;
@Override
public String toString() {
return "Emp{id=" + id + ", name='" + name + "'}";
}
}
19 of 46 02/11/25, 10:21 am
JavaMap [Link]
20 of 46 02/11/25, 10:21 am
JavaMap [Link]
class Emp {
int id;
String name;
21 of 46 02/11/25, 10:21 am
JavaMap [Link]
22 of 46 02/11/25, 10:21 am
JavaMap [Link]
Detailed Explanation
2. Overriding hashCode() :
The hashCode() method is used by the HashMap to calculate
the index in the internal hash table where the key-value pair
will be stored. In our case, the hashCode() is overridden as
follows:
@Override
public int hashCode() {
return [Link](id); // Generate a hash code using the
'id' field.
23 of 46 02/11/25, 10:21 am
JavaMap [Link]
}
Appearance Add new Edit this post
3. Overriding equals() :
The equals() method is used to compare two Emp objects for
equality, based on their id . The overridden equals() method
ensures that two Emp objects with the same id are considered
equal, even if they are different instances.
@Override
public boolean equals(Object obj) {
if (this == obj) return true; // Same object reference
if (obj == null || getClass() != [Link]()) return
false; // Null or different class
Emp emp = (Emp) obj; // Cast the object to Emp
return id == [Link]; // Compare the 'id' fields for
equality
}
24 of 46 02/11/25, 10:21 am
JavaMap [Link]
4. OveAddrnew
Appearance ridiEditnthis
g posttoString() :
This method is overridden to make it easier to print out the
Emp objects.
@Override
public String toString() {
return "Emp{id=" + id + ", name='" + name + "'}";
}
This ensures that when you print the Emp object, it will
display its id and name fields in a readable format.
5. Using HashMap :
In the main method, we create a HashMap and insert Emp
objects as keys. The map stores the Emp objects with a
String value. When you call [Link](emp1) , it looks up
the key using the hashCode() and equals() methods to find
the correct entry.
25 of 46 02/11/25, 10:21 am
JavaMap [Link]
6. Handling Collisions:
In our case, both emp1 and emp2 have id values that result
in the same hash code (due to id % 16 ), which causes a
collision. The HashMap handles this collision by storing the
entries in a linked list or tree structure within the same
bucket. When retrieving values, it uses equals() to
differentiate between the entries and returns the correct
one.
Output:
The output will be as follows:
Employee 1
Employee 17
Employee 2
HashMap contents: {Emp{id=1, name='Nitesh'}=Employee 1,
Emp{id=17, name='Ajay'}=Employee 17, Emp{id=2, name='Ravi'}
=Employee 2}
26 of 46 02/11/25, 10:21 am
JavaMap [Link]
Avoid Them
Appearance
Add new Edit this post
1. What is a Collision?
A collision happens when two or more distinct keys produce
the same hash value, meaning they would be placed in the same
bucket. For example:
• hash("key1") == hash("key2")
• This results in both keys being stored in the same
bucket, causing a collision.
27 of 46 02/11/25, 10:21 am
JavaMap [Link]
@Override
public int hashCode() {
return [Link](field1, field2);
}
You can set the initial capacity and load factor when
creating the HashMap .
28 of 46 02/11/25, 10:21 am
JavaMap [Link]
29 of 46 02/11/25, 10:21 am
JavaMap [Link]
• When
Appearance
a collision
Add new
occurs (i.e., multiple keys
Edit this post
hash to the same bucket), the HashMap stores
the key-value pairs in a linked list within
that bucket.
• This works well for a small number of
collisions, but as the number of collisions
increases, the performance degrades to O(n),
where n is the number of elements in the
bucket.
Example:
// Bucket 3: [Apple -> 10, Banana -> 20, Cherry -> 30, Date -
> 40] (Using Red-Black Tree)
30 of 46 02/11/25, 10:21 am
JavaMap [Link]
31 of 46 02/11/25, 10:21 am
JavaMap [Link]
32 of 46 02/11/25, 10:21 am
JavaMap [Link]
TreeMap , on Edit
thethisother hand, uses a red-black
Appearance Add new post
tree structure and ensures O(log n) time
complexity for all operations, but it requires
the keys to be ordered.
4. What are the performance considerations when
dealing with collisions in HashMap ?
• If the HashMap has many collisions (i.e., many
keys hash to the same bucket), performance can
degrade from O(1) to O(n) for lookup,
insertion, and deletion operations. Using a
good hash function can help distribute keys
evenly across buckets, reducing the chances of
collisions.
5. What is the default initial capacity and load
factor of HashMap ?
• The default initial capacity is 16 and the default
load factor is 0.75. This means the map will resize
when it is 75% full.
Next→
LinkedHashMap Overview
LinkedHashMap is a hash table and linked list combination
that maintains the insertion order (or optionally access
order) of the keys. It implements the Map interface, like
HashMap , but adds extra functionality to maintain the
ordering of elements.
33 of 46 02/11/25, 10:21 am
JavaMap [Link]
Thread-Safety of LinkedHashMap
LinkedHashMap is not thread-safe by default. Like HashMap ,
if multiple threads access a LinkedHashMap concurrently, and
at least one of them modifies the map, it should be
externally synchronized (e.g., using
[Link]() or ConcurrentHashMap if thread
safety is required).
Thread-Safety Workaround
If thread safety is a concern, you can:
• Use [Link](new
LinkedHashMap<K, V>()) to make it synchronized.
• Or, you can use ConcurrentHashMap , though it may
behave slightly differently due to its concurrent
access features.
34 of 46 02/11/25, 10:21 am
JavaMap [Link]
package [Link];
Appearance Add new Edit this post
import [Link];
import [Link];
35 of 46 02/11/25, 10:21 am
JavaMap [Link]
}
Appearance Add new Edit this post
}
}
package [Link];
import [Link];
import [Link];
// 1. Using keySet()
[Link]("Using keySet():");
for (String key : [Link]()) {
[Link](key + ": " + [Link](key));
}
// 2. Using values()
[Link]("\nUsing values():");
for (Integer value : [Link]()) {
[Link](value);
}
// 3. Using entrySet()
[Link]("\nUsing entrySet():");
for ([Link]<String, Integer> entry :
[Link]()) {
[Link]([Link]() + ": " +
[Link]());
}
36 of 46 02/11/25, 10:21 am
JavaMap [Link]
}
Appearance Add new Edit this post
🧠 What is
ConcurrentHashMap ?
ConcurrentHashMap is part of [Link] and is a
thread-safe version of HashMap .
🎮 Gaming Example
Use Case: Multiplayer Online
Game
Scenario:
You have a game server managing player scores in real time.
Multiple threads update scores as players perform actions
like kills, assists, etc.
🔧 Code Example:
java
import [Link];
37 of 46 02/11/25, 10:21 am
JavaMap [Link]
[Link]();
[Link]();
[Link]();
try {
[Link]();
[Link]();
[Link]();
} catch (InterruptedException e) {
[Link]();
}
38 of 46 02/11/25, 10:21 am
JavaMap [Link]
🔍 Key Add
Methods
Appearance new Edit Used:
this post
• merge() :
Atomically updates the score. If the player
exists, it adds the points; if not, it inserts the
new player with points.
• Thread-safe:
No need for external synchronization (like
synchronized blocks or locks).
🔄 How It Works
Internally
(Simplified):
• Internally uses segments (or buckets) for
partitioned locking — allowing multiple threads to
update different parts of the map without blocking
each other.
• Lock striping: Only locks the bucket needed,
unlike Hashtable which locks the entire map.
• Non-blocking reads: Reads usually happen without
locking.
✅ Yes (better
Thread-safe ❌ No ✅ Yes
performance)
Performance
(multi- ❌ Low ⚠ Poor ✅ High
thread)
39 of 46 02/11/25, 10:21 am
JavaMap [Link]
Feature
Appearance Add newHashEdit
Mapthis Hpost
ashtable ConcurrentHashMap
How
ConcurrentHashMa
p Works
Internally in
Java — Step by
Step Explanation
ConcurrentHashMap is a thread-safe variant of HashMap
introduced in Java to allow concurrent read and write
operations without locking the entire map. It is widely used
in multithreaded environments where you want to achieve high
throughput with minimal contention.
What is
ConcurrentHashMap ?
• A concurrent, thread-safe implementation of the
Map interface.
• Allows multiple threads to read and write
concurrently.
• Does not lock the entire map during updates.
• Uses internal partitioning (segments or bins) and
40 of 46 02/11/25, 10:21 am
JavaMap [Link]
Why
ConcurrentHashMap ?
Regular HashMap is not thread-safe and can cause data
inconsistency or infinite loops if used concurrently.
Hashtable is thread-safe but locks the entire table on every
operation, leading to poor performance.
How
ConcurrentHashMap
Works Internally?
1. Data Structure & Partitioning
• Internally, it uses an array of nodes (buckets),
similar to HashMap .
• Earlier versions (Java 7) used Segments — an array
of lockable segments, each responsible for a part
of the map.
• From Java 8 onwards, it uses a lock-free
optimistic concurrency control with CAS operations
and synchronized blocks only for bucket-level
locking.
• Buckets are linked lists or balanced trees (red-
black trees) if bucket size exceeds a threshold.
Insert (put):
41 of 46 02/11/25, 10:21 am
JavaMap [Link]
• Compute
Appearance
the hashEditof
Add new
the key.
this post
• Find the appropriate bucket index by (hash & (n -
1)) where n is table size.
• If bucket is empty, use CAS (Compare-And-Swap) to
insert node.
• If bucket exists:
◦ If bucket is a linked list, lock the bucket
node and insert/update the key.
◦ If bucket is a tree (due to many collisions),
perform tree-based insert.
• Update count using atomic operations.
• Resize if necessary.
Get:
• Compute hash of the key.
• Find bucket index.
• Traverse bucket to find the key (linked list or
tree).
• Return value if found, else null.
• No locking required for get (reads are mostly
lock-free).
Remove:
• Compute hash and find bucket.
• Lock bucket, remove node if present.
• Update count atomically.
42 of 46 02/11/25, 10:21 am
JavaMap [Link]
43 of 46 02/11/25, 10:21 am
JavaMap [Link]
collision exists.
Appearance Add new Edit this post
• Volatile variables: Ensure visibility of changes.
• Treeify: When bucket linked list length > 8,
convert to balanced tree for efficient lookup.
+----------------------------+
| Check if key exists
|
| / \
|
Yes update No insert new
node |
|
|
Update value Lock
bucket node
Add new
node at end
6. Benefits of ConcurrentHashMap
Feature Benefit
Lock-free
Fast concurrent reads
reads
44 of 46 02/11/25, 10:21 am
JavaMap [Link]
Feature
Appearance Add new Benefthis
Edit it post
🧩 Summary:
• ConcurrentHashMap is critical for concurrent
programming where shared state (like a scoreboard)
is updated by multiple threads.
• Offers high concurrency, low contention, and safe
access without external locks.
• Ideal for high-performance apps like games, real-
time systems, or servers.
45 of 46 02/11/25, 10:21 am
JavaMap [Link]
43 min read
By Nitesh Synergy
SHARE
46 of 46 02/11/25, 10:21 am