π· 1. HashMap
- Unordered: Does not maintain any order of keys.
- Allows null keys and values (one null key allowed).
- Not thread-safe.
- Time complexity: O(1) for
get()
andput()
(on average). - β Best for general-purpose use when order is not important.
Map<String, Integer> map = new HashMap<>();
β Use When:
- You need fast access(O(1) time complexity for basic operations)
- Order of elements doesn't matter.
- You are working in a single-threaded environment.
π§ Example Use Case:
- Caching results of expensive calculations
- Storing user profiles by user ID.
π· 2. LinkedHashMap
- Maintains insertion orderof keys.
- Allows null keys and values.
- Not thread-safe.
- Not thread-safe.
- Slightly slower than
HashMap
due to ordering overhead. - β Best when you need predictable iteration order.
Map<String, Integer> map = new LinkedHashMap<>();
β Use When:
- You want to maintain insertion order.
- Need fast access.withpredictable iteration.
π§ Example Use Case:
- Implementing LRU cache (can remove the
oldest entry using
.removeEldestEntry()
) - Keeping track of items accessed in the order they were added.
π· 3. TreeMap
- Sorted map based on keys (natural order
or custom
Comparator
) - Does not allow null keys (throws
NullPointerException
). - Not thread-safe.
- β Best when you need sorted keys.
Map<String, Integer> map = new TreeMap<>();
β Use When:
- You need to keep keys sorted (natural order or with a custom comparator)
- You're doing range queries(like getting all keys between two values).
Example Use Case:
- Storing items in a leaderboard or ranking system.
- Keeping a schedule or calendar sorted by date
π· 4. Hashtable
- Legacy class, synchronized (thread-safe).
- Does not allow null keys or values.
- Slower than
HashMap
due to synchronization. - β
Best when thread safety is needed and
you can't use
e ConcurrentHashMap.
Map<String, Integer> map = new Hashtable<>();
β Use When:
- You need a synchronized map for thread safety (older applications)
- You're maintaining legacy code.
Example Use Case:
- Shared configuration settings in legacy multi-threaded applications.
π· 5. ConcurrentHashMap
- Thread-safe without locking the whole map.
- Does not allow null keys or values.
- High performance in concurrent environments.
- β Best for multi-threaded applications.
Map<String,Integer> map = new ConcurrentHashMap<>();
β Use When:
- You're in amulti-threaded environment.
- You need athread-safe map without locking the entire structure.
- High concurrency is required.
π§ Example Use Case:
- Caching data in aweb application with many threads.
- Storing active user sessions.
β Java Map Comparison Table
Feature / Type | HashMap | LinkedHashMap | TreeMap | Hashtable | ConcurrentHashMap |
---|---|---|---|---|---|
Ordering | No order | Insertion order | Sorted (by key) | No order | No order |
Null Keys/Values | 1 null key, multiple null value | Same as HashMap | β No null keys, allows null values | β No nulls at al | β No nulls at all |
Thread-Safe | β No | β No | β No | β Yes (synchronize d | β Yes (high concurrency) |
Performance | Fastest(O(1)) | Slightly slower than HashMap | Slower(O(log n)) | Slower due to sync | Very fast, scalable |
Use Case | General-purpose | Predictable iteration | Sorted Data | Legacy multi-threaded | High-performance concurrency |
Custom Sorting | β No | β No | β Yes (Comparator) | β No | β No |
Best For | Caching, key-value storage | LRU cache, ordered data | Sorted leaderboard, ranges | Legacy apps | Web apps, shared caches |
β Internal Working of HashMap β Step by Step
π‘ Basic Concept:
- Each key is hashed into an integer hash code.
- The hash code determines the index(bucket) in an internal array where the key-value pair will be stored.
- If two keys land in the same bucket (hash collision), Java handles it using LinkedList or TreeNode (from Java 8+).
Let's Take an Example:
import java.util.*;
public class HashMapExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("apple", 100);
map.put("banana", 200);
map.put("orange", 300);
System.out.println("apple: " + map.get("apple"));
}
}
π§ Behind the Scenes:
Step 1: Hashing the Keys
Letβs say the internal array has a default capacity of 16.
int hash = "apple".hashCode(); // Let's say this gives 93029210
int index = hash % 16; // 93029210 % 16 = 2
So, the entry ("apple", 100) is stored in bucket 2.
Step 2: Putting More Entries
map.put("banana", 200);
β’ "banana".hashCode() might return, say, 2059142
β’ 2059142 % 16 = 6 β store in bucket 6
map.put("orange", 300);
β’ "orange".hashCode() β say, 7539312
β’ 7539312 % 16 = 0 β store in bucket 0
So the internal array (table)
now looks like:
Index | Entries
--------------------------
0 | ("orange", 300)
2 | ("apple", 100)
6 | ("banana", 200)
Others| null
Step 3: Getting a Value
map.get("apple");
β’ "apple".hashCode() = 93029210
β’ 93029210 % 16 = 2 β Go to index 2
β’ Search for the key using .equals() β Found β Return 100
π― 1. Collision Scenario in HashMap
β What is a Collision?
A collision happens when two different keys generate the same bucket index. This can happen even if the keys are different, just because their hash codes resolve to the same array index.
π§ͺ Example:
Map<String, Integer> map = new HashMap<>();
map.put("FB", 10); // Let's say hashCode() = 2236
map.put("Ea", 20); // Also has hashCode() = 2236
Both "FB" and "Ea" happen to have the same hashCode() (yes, this is a known trick example).
Assuming capacity is 16:
index = hashCode % 16 = 2236 % 16 = 12
How It Retrieves the Right Value:
- When you call
map.get("FB")
: - HashMap goes to index 12
- Compares each key using
.equals()
until it finds"FB"
2. Duplicate Key Scenario in HashMap
β What Happens If You Add the Same Key Again?
If you add a key that already exists in the map, HashMap updates the value β it does not create a new entry.
Example:
Map<String, Integer> map = new HashMap<>();
map.put("apple", 100);
map.put("apple", 200); // Same key, different value
- "apple"'s hashCode and bucket index are the same both times.
- The second put() overwrites the existing value.
π Final State of the Map:
{ "apple": 200 }
Only one key "apple"
exists, and its value is now updated to
200
.
π Visual Comparison
Scenario | Keys | HashCode | Bucket Index | Result |
---|---|---|---|---|
Collision | "FB", "Ea" | Same (e.g., 2236) | Same | Stored together in one bucket |
Duplicate Key | "apple" twice | Same | Same | Old value replaced with new |