Skip to content

Intermediate · The Standard Template Library (STL) · topic 22 of 42 · 30 min

std::map and std::unordered_map

Explanation

A map stores key–value pairs, like a phone book from name to number. std::map keeps keys sorted (a balanced tree, O(log n) per operation); std::unordered_map uses hashing (O(1) on average, no order). Beware: map[key] inserts a default value when the key is missing; use find, count or contains to only check.

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.

cpp
#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
}
std::map keeps keys in sorted order. [item, qty] is a structured binding (covered in the modern C++ module).

The operator[] trap

cpp
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++20
operator[] creates a default value for a missing key. That is handy for counting, but wrong for "just checking". It also cannot be used on a const map.

Counting with a map

cpp
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';         // 3
Here operator[] inserting 0 is exactly what you want.

map versus unordered_map

std::mapstd::unordered_map
Insidebalanced binary search tree (usually red-black)hash table
Find / insert / eraseO(log n)O(1) on average, O(n) worst case
Order when you loopsorted by keyno useful order
Key needsoperator< (or a comparator)std::hash and operator==
Extra trickslower_bound / upper_bound for ranges of keysreserve(n) to avoid rehashing
Think of it like this: std::map is like a dictionary book: words are in alphabetical order, so you can find a word by opening near the right page (O(log n)) and also read all words starting with "ka" together. std::unordered_map is like a wall of numbered lockers where a formula (the hash) turns a name straight into a locker number: usually one step, but no order at all.

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).

Careful: On contest sites like Codeforces, people sometimes craft tests that make std::unordered_map<int,int> slow with many collisions (an "anti-hash" test), turning an O(n) solution into O(n²) and a Time Limit Exceeded. If that happens, use std::map, or a custom hash with a random seed.

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.
Tip: Need sorted output or "the first key greater than X"? Use std::map. Just need fast lookups by key? Use std::unordered_map. When unsure, start with std::map; it is predictable.

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

Maps

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.

cpp
#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 3
std::map sorts the cities for free.

Practice (0/4 done)

Task 1 · Question

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?

Task 2 · Question

What does this print? std::map<std::string, int> m = {{"x", 1}}; int v = m["y"]; std::cout << v << " " << m.size();

Task 3 · Question

You need the average lookup time to be O(1) and you never need sorted output. Which container?

Task 4 · Practice

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

Question 1

1.What is the time to find a key in std::map with n keys?

Question 2

2.Which call returns end() when the key is missing, without inserting?

Question 3

3.Which can you NOT do with std::unordered_map that you can with std::map?

Question 4

4.What is the worst-case lookup time of std::unordered_map?

Question 5

5.How do you read a value from a const std::map without risk of insertion?

Read more (free)

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.

From Hash maps and hash sets

Which order does std::queue follow?Related

Answer: First in, first out

A queue serves elements in the order they arrived.

From set, stack, queue, deque and priority_queue

What is the average lookup time of a well-sized hash table?Related

Answer: O(1)

With a good hash and low load factor.

From Hash tables

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

  1. 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.
  2. Module 6 exam: The STL · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Templates, smart pointers and move semantics. 42 topics left in the course before the final exam.

← Previous: std::vector in depth