🚀 Phases 1–4 are live — Days 1–13 + Day 17 are fully written. See the roadmap →

Using Hash Maps in Real Code

You almost never write a hash map from scratch. Every language ships one, and they’re battle-tested by millions of programs. This page covers the stdlib API in C++, Python, and Java, plus four patterns that solve 90% of interview problems.

The four core operations

Every language exposes the same fundamental API. Here’s the Rosetta stone:

OperationC++PythonJava
Create emptyunordered_map<K, V> m;m = {}Map<K, V> m = new HashMap<>();
Put / setm[k] = v;m[k] = vm.put(k, v);
Getm[k] (creates if missing!)m[k] (KeyError if missing)m.get(k)
Get with defaultm.count(k) ? m[k] : defaultm.get(k, default)m.getOrDefault(k, default)
Contains keym.count(k) > 0 or m.contains(k)k in mm.containsKey(k)
Deletem.erase(k);del m[k]m.remove(k);
Sizem.size()len(m)m.size()
Iterate keys + valuesfor (auto& [k, v] : m)for k, v in m.items():for (var e : m.entrySet())
⚠️

C++ trap: m[k] on a missing key silently inserts a default-constructed value (e.g. 0 for int). Use m.count(k) or m.find(k) first if you don’t want that. Python’s m[k] correctly throws KeyError; Java’s m.get(k) returns null.

Pattern 1: Counting frequencies

By far the most common use. Walk a sequence, build {element: count}.

This single pattern powers Top K Frequent, Sort Characters by Frequency, First Unique Character, Find All Anagrams, Group Anagrams, and many more.

Pattern 2: Seen-set for O(1) “have I seen this?”

A HashSet (or a HashMap you only use the keys of) lets you answer “have I encountered x before?” in O(1).

Set.add(x) returning false for duplicates (Java) and set.add(x) being a no-op (Python) are useful idioms — they fold “check + insert” into one operation.

Pattern 3: Value → original-index map (the Two Sum trick)

A hash map can also map values to indices. This is the trick behind Two Sum and most “find two elements that satisfy X” problems.

def two_sum(nums, target):
    seen = {}                              # value → index
    for i, x in enumerate(nums):
        complement = target - x
        if complement in seen:
            return [seen[complement], i]
        seen[x] = i
    return []

The pattern generalizes: any time you need to know “is the partner of this element somewhere in the past?”, a value → index map answers in O(1).

Pattern 4: Grouping (bucket by a key signature)

When you need to group items that share a property — anagrams (same sorted letters), points on the same line (same slope from origin), etc. — a hash map keyed by the signature does it in one pass.

Choosing a good signature is the whole art of the bucket pattern. Sort the characters? Use a tuple of counts? Hash the chars in a particular way? Whatever makes “same group” easy to express as a hash key.

HashMap vs HashSet — when to use which

The difference is small but important:

  • HashSet<T> stores keys only. Use when you only care whether something is present.
  • HashMap<K, V> stores keys mapped to values. Use when you need additional info per key (counts, indices, lists of items).

In practice, Set is just Map<K, Boolean> with a friendlier API. Pick the one whose API reads cleanest in your problem.

Caveats and edge cases

A few real-world cracks to be aware of:

  1. Iteration order is not guaranteed. unordered_map (C++) and HashMap (Java) iterate in implementation-defined order. Python 3.7+ guarantees insertion order for dict (and Java has LinkedHashMap for this). Don’t rely on hash-map iteration order unless you’ve explicitly checked the language spec.

  2. Concurrent modification is unsafe. Modifying a hash map while iterating over it crashes in Java (ConcurrentModificationException), corrupts in C++, and raises RuntimeError in Python. Snapshot the keys first if you need to delete during iteration.

  3. NaN as a key is weird. NaN != NaN, so you can insert it but never look it up. Avoid.

  4. Custom keys need both hash and equals. Override one without the other and your map will silently misbehave. Java’s IDE-generated hashCode + equals is the safe path. Python uses __hash__ + __eq__.

The mental shortcut for problem-solving

When you’re stuck on a problem, ask:

“If I had a magic spell that could check ‘have I seen this value (or this signature) before?’ in O(1), would this be easier?”

If yes — and it almost always is — that magic spell is a hash map. Add it to your solution; you’ve usually just collapsed a quadratic problem to linear.

Time to flex it on real problems.