Intermediate · The Standard Template Library (STL) · topic 22 of 42 · 30 min
std::map and std::unordered_map
Explanation
Why maps?
Often you need to look things up by a name or ID instead of a position: the price of an item by its code, the number of votes per candidate, the stock left per product. A map (also called a dictionary or associative array) stores pairs of key and value, and finds the value for a key quickly. Each key appears at most once.
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> stock;
stock["rice"] = 40;
stock["dal"] = 25;
stock["atta"] = 60;
stock["rice"] -= 5; // update existing key
for (const auto& [item, qty] : stock) { // sorted by key
std::cout << item << ": " << qty << '\n';
}
// atta: 60
// dal: 25
// rice: 35
}The operator[] trap
std::map<std::string, int> price = {{"tea", 15}};
if (price["coffee"] == 0) { // BUG: this INSERTS "coffee" with value 0
std::cout << "not sold\n";
}
std::cout << price.size(); // 2, not 1
// Correct ways to check:
if (price.count("coffee") == 0) { } // count is 0 or 1 for map
if (price.find("coffee") == price.end()) { } // find returns end() when missing
if (!price.contains("coffee")) { } // C++20Counting with a map
std::vector<std::string> votes = {"Asha", "Ravi", "Asha", "Meena", "Asha"};
std::unordered_map<std::string, int> count;
for (const auto& v : votes) ++count[v]; // missing keys start at 0
std::cout << count["Asha"] << '\n'; // 3map versus unordered_map
| std::map | std::unordered_map | |
|---|---|---|
| Inside | balanced binary search tree (usually red-black) | hash table |
| Find / insert / erase | O(log n) | O(1) on average, O(n) worst case |
| Order when you loop | sorted by key | no useful order |
| Key needs | operator< (or a comparator) | std::hash and operator== |
| Extra tricks | lower_bound / upper_bound for ranges of keys | reserve(n) to avoid rehashing |
Hashing in one paragraph
A hash function turns a key (like "rice") into a number. The unordered_map uses that number to choose a bucket (a slot in an internal array). Different keys can land in the same bucket (a collision); then the map must compare keys inside the bucket. With a good hash, buckets stay small and lookups are O(1) on average. With a bad hash or carefully chosen hostile input, everything lands in one bucket and lookups become O(n).
Useful operations
- m.insert({key, value}) or m.emplace(key, value) adds only if the key is not there yet.
- m.insert_or_assign(key, value) (C++17) adds or overwrites.
- m.erase(key) removes a key.
- m.at(key) returns the value or throws std::out_of_range if the key is missing (works on const maps).
- std::multimap / std::unordered_multimap allow repeated keys.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
std::map and std::unordered_map · 1/6
A map stores key value pairs and finds a value by its key, like a phone book.
Prefer a video by a teacher? Find free videos on “c++ std::map vs unordered_map tutorial find count operator[]” on YouTube ↗
In real life: Counting orders per city
A food-delivery company wants the number of orders per city for yesterday, printed in alphabetical order for a report. Counting with a std::map gives both the counts and the sorted order in one step.
#include <iostream>
#include <map>
#include <string>
#include <vector>
int main() {
std::vector<std::string> orders = {"Pune", "Delhi", "Pune", "Chennai", "Delhi", "Pune"};
std::map<std::string, int> perCity;
for (const auto& city : orders) ++perCity[city];
for (const auto& [city, n] : perCity) std::cout << city << ' ' << n << '\n';
}
// Chennai 1
// Delhi 2
// Pune 3Practice (0/4 done)
std::map<std::string, int> m; m["b"] = 2; m["a"] = 1; m["c"] = 3; In what order does a range-for print the keys?
What does this print? std::map<std::string, int> m = {{"x", 1}}; int v = m["y"]; std::cout << v << " " << m.size();
You need the average lookup time to be O(1) and you never need sorted output. Which container?
Read a paragraph of words (until end of input) and print the 3 most frequent words with their counts. Use std::unordered_map<std::string, int> to count, then copy the pairs into a vector and sort it by count (highest first, then alphabetically for ties).
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- set, stack, queue, deque and priority_queueThe Standard Template Library (STL) · same module
- Iterators: the glue between containers and algorithmsThe Standard Template Library (STL) · same module
- Hash maps and hash setsData Structures and Algorithms (DSA) for interviews · Hashing, two pointers and sliding window
- Hash tablesC Programming (from zero to systems) · Data structures in C
- HashMap and HashSetRust Programming · Error handling and collections
- Maps: key-value look-upsGo Programming (backend and cloud) · Collections and structs
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What is the time to find a key in std::map with n keys?
Answer: O(log n)
std::map is a balanced tree, so its height is about log n.
Which call returns end() when the key is missing, without inserting?
Answer: m.find(key)
find only searches. at throws; [] inserts.
Which can you NOT do with std::unordered_map that you can with std::map?
Answer: Loop in sorted key order
unordered_map has no ordering, so no sorted iteration or lower_bound.
What is the worst-case lookup time of std::unordered_map?
Answer: O(n)
If many keys collide into one bucket, a lookup checks them one by one.
How do you read a value from a const std::map without risk of insertion?
Answer: m.at(key) or m.find(key)
operator[] is not allowed on const maps because it may insert; at and find are.
When can a hash map lookup become O(n)?Related
Answer: When many keys collide into the same bucket or probe sequence
If most keys share a bucket, a lookup has to check them one by one.
Which order does std::queue follow?Related
Answer: First in, first out
A queue serves elements in the order they arrived.
What is the average lookup time of a well-sized hash table?Related
Which key type cannot be used in a std HashMap?Related
Answer: f64
f64 does not implement Hash and Eq, because NaN is not equal to itself.
From HashMap and HashSet
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 3 more topics in “The Standard Template Library (STL)” before its exam: set, stack, queue, deque and priority_queue, Iterators: the glue between containers and algorithms, STL algorithms: sort, find, count, accumulate and binary search.
- Module 6 exam: The STL · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Templates, smart pointers and move semantics. 42 topics left in the course before the final exam.