C++ map vs unordered_map: Lookup and Examples
Learn C++ map and unordered_map with clear key-value examples, ordered versus hash lookup, find without insertion, word counting and safe missing-key handling.
What you will learn
- Explain a key-value pair using a word-frequency example.
- Choose ordered map output or hash-based lookup for a stated need.
- Use operator[] deliberately for counting and find for read-only lookup.
- Handle a missing key without adding an accidental zero entry.
- Test duplicate words, empty data and unchanged lookup size.
Use a map when you ask for a value by name
A vector answers questions such as what is the value at position two. A frequency report asks a different question: how many times did the word pear appear? The word is a key, and its count is the associated value. A map stores these relationships so you can look up a key without keeping two parallel vectors or searching a list of unrelated positions by hand.
Write std::map<std::string, int> when keys are strings and counts are integers. Each key appears at most once in this map type. Repeated occurrences of the same word should update its existing count, not create another independent key. Distinguish the number of keys from the total number of observed words: pear appearing three times is one key whose stored value is three.
std::unordered_map also stores unique keys and their associated values, but uses a different organization for lookup. Both are owning containers: their string keys and integer values belong to the container. They are not merely views of the input line. Choosing between them is about ordering, lookup behavior and other design needs, not a rule that one container is always the modern replacement for the other.

Choose ordered output when ordering is part of the answer
std::map keeps keys in the order defined by its comparison rule. With the default string comparison and this lesson's lowercase English word inputs on the documented toolchains, the example prints apple before pear. This makes it useful for a report that must have stable key ordering. The container does not sort values by frequency unless you ask a separate algorithm to organize a different result structure.
std::unordered_map uses hashing to organize key lookup. Its iteration order is not a promise of alphabetical order, input order or random order. It may change when the container changes or when you use another implementation. If your required output is sorted, do not compare an observed hash-table printout with a desired sorted transcript and hope it stays that way. Use an ordered representation or sort the report separately.
For lookup complexity, map offers logarithmic behavior in the number of elements. Unordered lookup is average constant-time but can be linear in the worst case. Those descriptions are not a guarantee that hashing always runs faster for your actual data. Key comparison costs, memory, hash quality and workload matter. A hash used for table lookup is also not a claim of encryption or password security. Keep these different uses of the word hash separate.
Count repeated words and print distinct keys
operator[] is intentional here: counting a new word should create its count. The map then reports keys in its comparison order.
Predict the output, edit the source, then select Run code.
Compare with the starter's expected output
apple: 1
pear: 2
Keys: 2
After editing inputs, calculate a new prediction; this reference describes only the starter.
operator[] can insert; find only searches
For these maps with int values, counts[word] finds the word or creates it with a value-initialized count of zero. Incrementing that result is a convenient way to count an occurrence. It is a writing operation, even when it looks like an ordinary indexed read. That is why a lookup such as counts[query] can accidentally add a word the input never contained.
Use find when the question is only whether a key exists and what value it already has. The returned iterator identifies the existing entry, or equals end() when no key is found. Check that comparison before reading it->second. The first component of the pair is the key and the second is its stored value; neither the missing-key branch nor the act of searching needs to insert a new entry.
at is another option when a missing key should be reported through an exception, while contains can answer a presence question in C++20. We focus on find because it supplies both the presence result and access to the stored count with one search. Avoid checking with contains and then using operator[] thoughtlessly in a different mutation-heavy context. First choose the intended lookup contract, then use the operation that directly expresses it.
Search a missing key without changing the hash table
No kiwi entry exists before or after this lookup. Do not depend on unordered iteration to obtain a particular report order.
Predict the output, edit the source, then select Run code.
Compare with the starter's expected output
Not found
Before: 1
After: 1
After editing inputs, calculate a new prediction; this reference describes only the starter.
Read entries carefully and respect each container's iterator rules
A map entry pairs a key with a value. In the simple reporting loop, const auto& entry observes that pair without copying its string for each printed line. entry.first names the key and entry.second names the count. You cannot normally rewrite a stored key through that pair as if it were an ordinary mutable string: doing so could break the container's organization. Remove and insert according to a deliberate update design if a key must change.
When you change a container during a traversal, its iterator rules matter. An unordered_map rehash invalidates iterators, though references and pointers to existing elements remain valid unless those elements are erased. Do not keep using an old iterator across growth that may rehash. The lab avoids the problem by finishing every insertion before it begins its report and lookup, making the phases clear to a beginner.
The two-container lab is for comparison, not a recommendation to duplicate every production collection. We build matching counts in a map for ordered reporting and an unordered_map for the lookup demonstration. A real application might need only one. Showing both lets you separate the chosen output order from read-only lookup behavior without pretending that the two internal data structures have identical costs or mutation rules.
- Collect and validate a word.
- Increment its stored count intentionally in each container.
- Finish insertion before reporting or retaining a lookup iterator.
- Compare a find result with end before reading the stored count.
Use small input rules so the container behavior stays visible
Read a count from zero through eight, then that many word lines and one query line. Each word and query must contain one through twelve lowercase English letters only, with no spaces or trimming. The accepted letter set is written explicitly in the validation helper. Malformed counts, missing required lines or invalid words print Invalid input and return status one without a partial report. These rules are not a multilingual tokenizer.
After accepted input, print the map's ordered frequency rows, then find the query in the unordered_map. Print Lookup with its count or not found, followed by Keys before and Keys after for that hash table. The two sizes must match because the query is read-only. A count of zero is valid input data: it produces no frequency rows and a missing query result, with zero keys before and after.
Test repeated words, all distinct words, an existing query, a missing query and the eight-word maximum. Include an uppercase spelling, a space, an overlong word, a missing query and a final query line without a newline. As a repair exercise, replace find with operator[] in a separate experiment and predict the new missing-key count. Then restore find and verify that observation does not quietly change the data you are trying to observe.
Compile one program and compare its output
The lesson editors run complete programs only when the compiler sandbox is available. You can also save one example as main.cpp and use your installed compiler. Run only the repaired version of an intentional compile-error example.
macOS / Linux (choose your compiler):
clang++ -std=c++20 -Wall -Wextra -Wpedantic main.cpp -o lesson
# Or: g++ -std=c++20 -Wall -Wextra -Wpedantic main.cpp -o lesson
./lesson
Windows Developer Command Prompt:
cl /std:c++20 /EHsc /W4 main.cpp /Fe:lesson.exe
lesson.exeIndependent lab
Count a bounded list of words, print ordered frequencies, then search a query without adding a missing key.
Acceptance checklist
- Read a complete count in 0..8, that many word lines and one query line.
- Accept only 1–12 lowercase English letters per word or query; reject bad or missing input as Invalid input with status 1 before reporting.
- Count occurrences in both map and unordered_map, using operator[] only for intentional count updates.
- Print frequency rows from map and use find on unordered_map for the query.
- Print Lookup, Keys before and Keys after; a missing lookup must not change key count.
Need a hint?
- Store and validate all required input before writing the accepted report.
- The map's size counts distinct words, not input lines.
- The missing find result equals end; do not follow it or replace it with an inserting lookup.
Write and run your lab
Build your own solution before revealing the reference. Use the input field for normal, boundary and invalid cases; this runner executes your program but does not grade it.
Predict the output, edit the source, then select Run code.
Your lab evidence and notes
Record predictions, actual output, commands and the cause of each repair. Code is plain text: this scratchpad does not execute or grade C++.
Loading local notes…
Review your acceptance checklist and quiz explanations before marking this lesson complete. This is self-review, not a grade or certification.
Reveal the explained lab solution
Reference lab solution
Compare the reference with your own reasoning. Running this solution does not grade or complete the lesson.
Predict the output, edit the source, then select Run code.
Expected output
apple: 1
pear: 2
Lookup: not found
Keys before: 2
Keys after: 2
Each accepted word deliberately updates a count. With at most eight input words, the int frequency is bounded by eight.
The ordered map supplies stable report ordering, while find searches the hash table without creating an absent query key.
Comparing key counts before and after the query catches the common mistake of using an inserting operation for a read-only question.
Review before moving on
Explain the lesson's objectives in your own words, compare your lab evidence with the acceptance checklist, and keep the first failing case alongside your repair. Completing a page is not proof that every C++ feature or input is supported.
- Explain a key-value pair using a word-frequency example.
- Choose ordered map output or hash-based lookup for a stated need.
- Use operator[] deliberately for counting and find for read-only lookup.
- Handle a missing key without adding an accidental zero entry.
- Test duplicate words, empty data and unchanged lookup size.
References and further reading
Original examples and exercises accompany these primary references. Tool-specific diagnostics and support depend on your installed version.