Implement a HashMap Algorithm
Every language gives you a built-in hash map. But building one from scratch teaches you what's actually happening under the hood — and why performance can...
10 Apr 2024

Every language gives you a built-in hash map. But building one from scratch teaches you what's actually happening under the hood — and why performance can vary so wildly.
What a HashMap Does
It stores key-value pairs. You give it a key, it returns the value. Average O(1) for get, set, and delete.
Under the hood: a hash function converts the key into an array index. The value goes into that slot. Collisions (two keys landing in the same slot) are handled by chaining — storing a list at each slot.
The Implementation
class HashMap {
constructor(size = 53) {
this.buckets = new Array(size);
this.size = size;
}
_hash(key) {
let hash = 0;
const prime = 31;
for (let i = 0; i < key.length; i++) {
hash = (hash * prime + key.charCodeAt(i)) % this.size;
}
return hash;
}
set(key, value) {
const index = this._hash(key);
if (!this.buckets[index]) {
this.buckets[index] = [];
}
const existing = this.buckets[index].find(([k]) => k === key);
if (existing) {
existing[1] = value;
} else {
this.buckets[index].push([key, value]);
}
}
get(key) {
const index = this._hash(key);
const bucket = this.buckets[index];
if (!bucket) return undefined;
const pair = bucket.find(([k]) => k === key);
return pair ? pair[1] : undefined;
}
delete(key) {
const index = this._hash(key);
const bucket = this.buckets[index];
if (!bucket) return false;
const i = bucket.findIndex(([k]) => k === key);
if (i === -1) return false;
bucket.splice(i, 1);
return true;
}
keys() {
const result = [];
for (const bucket of this.buckets) {
if (bucket) {
for (const [key] of bucket) {
result.push(key);
}
}
}
return result;
}
}
const map = new HashMap();
map.set("name", "Ehsan");
map.set("role", "engineer");
map.set("lang", "TypeScript");
console.log(map.get("name")); // "Ehsan"
console.log(map.get("role")); // "engineer"
map.delete("lang");
console.log(map.keys()); // ["name", "role"]
Complexity
| Operation | Average | Worst |
|---|---|---|
| get | O(1) | O(n) |
| set | O(1) | O(n) |
| delete | O(1) | O(n) |
Worst case happens when all keys hash to the same bucket. A good hash function and proper table sizing prevent this.
What's Missing
A production hash map also handles:
- Resizing — when the load factor (items / buckets) gets too high, double the bucket array and rehash everything. This keeps chains short.
- Better hashing — the simple polynomial hash works for strings but a production implementation uses more sophisticated algorithms.
- Non-string keys — you'd need a way to hash numbers, objects, etc.
The Trade-off
Hash maps are the go-to for fast lookups by key. But they use more memory than arrays, don't maintain insertion order (though JavaScript's Map does), and can't do range queries. If you need sorted access, use a balanced BST instead.
Production-Ready Systems with LLMs and Agents
A live Maven cohort, 5 October to 2 November: eight 90-minute sessions where you build LLM and agent systems that survive real traffic, real cost and real failure. Tuesdays and Thursdays, 7:30 to 9:00pm London.
Cohort 2 starts 5 October. Eight live sessions, $1,500.
View the live cohortKeep reading
- The Algorithms Worth Knowing in Code Review: Cutting Big O Without Being Clever
- Tracking Down the Mystery: Finding the Unique Delivery ID
- Elusive Least Occurring Number in an Array
- Solving the Height of a Binary Tree Puzzle
- Harry Potter Discounts: A Code Challenge Algorithm
- Implementing a Task Heap Service in TypeScript