Implement a Chaining Hash Map, Then Make It Thread-Safe and Distributed
Company: Applied Intuition
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Onsite
Implement a hash map similar to C++'s `std::unordered_map`, with insert or update, lookup and erase, resolving collisions by separate chaining. The discussion then moves to making the map safe for multithreaded use and to how the design could become a distributed system.
### Clarifying Questions
- Which operations are required: insert, insert-or-assign, find, erase, `operator[]`, iteration?
- Must pointers and references to stored values stay valid when the table grows, as they do for the standard container?
- Should it accept custom hash and equality functions, or only built-in key types?
- For the concurrent version, how many threads, and what mix of reads and writes?
### Part 1 — Implement the map with chaining
Implement insert-or-assign, find, erase and size for generic keys and values, with an array of buckets in which each bucket holds a chain of entries. Decide when the table grows and how.
```hint Growth
Ask what happens to the cost of a lookup as more keys land in the same number of buckets, and what must happen to every entry when the number of buckets changes.
```
#### What This Part Should Cover
- Correct insert, update, find and erase on the chains
- A load-factor threshold, rehashing, and the amortized and worst-case costs
- How a hash value becomes a bucket index, and what a weak hash function does to the chains
### Part 2 — Make it thread-safe
Many threads now read and write the map concurrently. Make it safe, and explain how your choice affects throughput.
```hint Which operations conflict
Consider which operations truly conflict with each other, and what a resize does to every other operation running at the same time.
```
#### What This Part Should Cover
- Lock granularity options and the one chosen for the workload
- Resizing while other threads use the map
- API pitfalls: returned references that outlive a lock, and check-then-act races
### Part 3 — Turn it into a distributed system
The data no longer fits on one machine, or must survive the failure of one. Explain how to distribute the map across machines.
```hint Finding the owner
Think about what a client needs to know to find the machine that holds a key, and what happens to that knowledge when a machine is added or fails.
```
#### What This Part Should Cover
- Partitioning the keys, and rebalancing when machines join or leave
- Replication, consistency and failure handling
- What changes compared with an in-process map
### What a Strong Answer Covers
- A correct, generic chaining implementation with load-factor-driven rehashing
- Complexity analysis, including the worst case under heavy collisions
- A concurrency design matched to the workload, with the resize and API pitfalls handled
- A distributed design whose partitioning, replication and consistency choices are justified
- Clear statements of which guarantees change at each step, from single-threaded to concurrent to distributed
### Follow-up Questions
- An attacker sends keys chosen to collide. What do you change?
- How does open addressing compare with chaining for cache behavior, deletion and reference stability?
- How would you grow the concurrent map without pausing every thread?
- In the distributed version, how would you support an atomic increment of a counter stored under one key?
Overview: A coding and design question: implement a hash map like the C++ unordered_map with separate chaining, then make it safe for concurrent threads and extend it into a distributed key-value system. It tests load factors and rehashing, lock granularity, partitioning, replication and consistency trade-offs.
Read the full Applied Intuition Software Engineer interview experience this question came from