
HashMap in C++ (unordered_map)
Introduction
If you're coming from Java or just starting out with C++, you might wonder — how do we store data in key-value pairs, like a dictionary? The answer in C++ is unordered_map
, a powerful and efficient way to store data where each value is associated with a unique key.
What is HashMap?
A HashMap is a data structure that allows you to store data in the form of key-value pairs.
Think of it like a real-world dictionary:
-
You look up a word (key)
-
And you get its definition (value)
It is part of the Standard Template Library (STL).
Syntax
std::unordered_map<key_type, value_type> variable_name;
Why Use unordered_map
?
Reason | Explanation |
---|---|
Fast Access | You can get the value for a key in O(1) time on average |
Unique Keys | Each key is stored only once |
Flexible | Supports many data types as keys and values |
Easy to Use | Works like a dictionary or address book |
How to Use unordered_map
in C++
1. Include the Required Header
#include <unordered_map>
2. Declare the Map
std::unordered_map<std::string, int> age;
This declares a map where:
-
Keys are strings (like names)
-
Values are integers (like ages)
Example
#include <iostream>
#include <unordered_map>
int main() {
std::unordered_map<std::string, int> age;
age["Alice"] = 25;
age["Bob"] = 30;
std::cout << "Alice is " << age["Alice"] << " years old.\n";
return 0;
}
Output
Alice is 25 years old.
How Does unordered_map
Work Internally ?
This part is important if you want to understand why it's fast.
Step 1: Hashing the Key
When you insert a key, like "Alice"
, the map uses a hash function to convert it into a number called a hash code.
std::hash<std::string> h;
size_t code = h("Alice"); // some integer value
Step 2: Buckets
The map uses that hash code to decide which bucket to store the key-value pair in. A bucket is like a slot in an array.
If two different keys have the same hash (rare, but possible), they go into the same bucket — this is called a collision.
Step 3: Collision Handling
Collisions are handled using linked lists or internal chains. Since C++11, performance during collisions is still very efficient.
Step 4: Rehashing
If your map grows too big, it automatically resizes (rehashing) to keep the access time fast.
Dry Run Example
std::unordered_map<std::string, int> scores;
scores["Alice"] = 85;
scores["Bob"] = 90;
scores["Charlie"] = 75;
std::cout << scores["Bob"]; // 90
scores.erase("Charlie"); // Removes Charlie
std::cout << scores.size(); // 2
What happens internally?
-
"Alice"
→ hashed and stored in bucket A -
"Bob"
→ stored in bucket B -
"Charlie"
→ stored in bucket C -
"Charlie"
is erased — now only 2 entries
Points to Remember
-
Keys must be unique — if you insert the same key again, it updates the value.
-
Order is NOT maintained — don’t expect the data to come out in the same order you inserted it.
-
Avoid
map["key"]
just to check if the key exists — it creates the key if it doesn't exist.
Key Operations
1. Insert Elements
std::unordered_map<std::string, int> age;
age["Alice"] = 25;
age["Bob"] = 30;
Here, "Alice"
is the key and 25
is the value. You can assign or update values using the same syntax.
2. Access Elements
std::cout << "Alice's age is " << age["Alice"] << "\n";
Note:
- If the key doesn’t exist, it is automatically inserted with a default value (e.g., 0 for
int
).
3. Check If a Key Exists
if (age.find("Alice") != age.end()) {
std::cout << "Alice is " << age["Alice"] << " years old.\n";
}
find("key")
returns an iterator:
-
If found → not equal to
end()
-
If not found → equals
end()
4. Remove an Element
age.erase("Bob"); // Deletes the key "Bob" and its value
5. Map Size
std::cout << "Size: " << age.size() << "\n";
6. Iterate Over the Map
for (const auto& pair : age) {
std::cout << pair.first << ": " << pair.second << "\n";
}
-
pair.first
→ key -
pair.second
→ value
Example
#include <iostream>
#include <unordered_map>
int main() {
// Declare an unordered_map where key = name, value = score
std::unordered_map<std::string, int> scores;
// Insert elements
scores["Alice"] = 90;
scores["Bob"] = 85;
scores["Charlie"] = 78;
// Access a value using key
std::cout << "Bob's score: " << scores["Bob"] << "\n";
// Check if a key exists before accessing it
if (scores.find("Alice") != scores.end()) {
std::cout << "Alice's score: " << scores["Alice"] << "\n";
}
// Update a value
scores["Alice"] = 95;
// Remove a key-value pair
scores.erase("Charlie");
// Size of the map
std::cout << "Number of students: " << scores.size() << "\n";
// Iterate over the map and print all values
for (const auto& entry : scores) {
std::cout << entry.first << ": " << entry.second << "\n";
}
return 0;
}
Output
Bob's score: 85
Alice's score: 90
Number of students: 2
Alice: 95
Bob: 85
Time and Space Complexity
Operation | Time Complexity (Average Case) | Space Complexity |
---|---|---|
Insert / Update | O(1) | O(n) |
Access | O(1) | O(n) |
Delete | O(1) | O(n) |
Search (find) | O(1) | O(n) |
Note: Worst case can go up to O(n), but it’s rare due to hashing.
Common Mistakes
Mistake | What Happens |
---|---|
Accessing missing key with [] |
Inserts a default value (0 for int) |
Expecting insertion order | Doesn’t work — order is random |
Using in multithreading | Not thread-safe — use mutex |
When to Use unordered_map
Use it when:
-
You want fast access to values using keys.
-
You don’t care about the order of elements.
-
You want an efficient alternative to arrays or map.
Conclusion
unordered_map
is one of the most powerful and commonly used STL containers in C++. If you ever need to store data that can be retrieved by a unique key — like phonebooks, user IDs, scores, or frequencies — unordered_map
is the perfect choice.
Its fast performance and simple syntax make it a must-have in every C++ programmer’s toolkit.
Related Blogs
For more amazing blogs
Click Here
Till then
Happy Coding!!!
3 Reactions
0 Bookmarks