Hash Map

What it is

A hash map stores a value for each key. A hash chooses a starting slot in an array. If that slot is taken, the table looks for another one. Two keys can choose the same starting slot. This is a collision.

The core idea

When a slot is already taken, the table checks the next slot, and the one after that, until it finds one that is free or that holds the key it wants (people call this linear probing). A slot can be empty, live, or deleted. A deleted marker lets a search continue past a removed key (people call this a tombstone). A key's location depends on the table size, so growth is more than copying an array. Extra empty space keeps searches short, at the cost of more memory.

Example

Keys A and B choose the same starting slot. A goes in that slot. B goes in the next one. Delete A, then search for B. The search must pass the deleted slot and still find B.

Where you meet this

When to choose it: you look things up by an exact key and do not need any order.

When not to: you need keys in sorted order or a range ("every key from 10 to 20"). A sorted tree or a sorted array does that, and a hash map cannot. Open addressing also slows down a lot when the table is nearly full, so it has to grow early. Chaining copes better with a full table but costs more memory per key.

Common bugs

Keep it fast

Keep enough empty space to make searches short. How full the table is, compared to its size, is called the load factor. Deleted markers also use search space. Too many of them can make a small table slow.

Learn more

Knuth's hashing chapter explains this in more depth. CPython's dict source and SwissTable design notes show production tables.

Go to the Hash Map challenge