← all posts

Hash maps changed the way I see every problem

·2 min read ·Computer Science · Algorithms · Performance

Competitive programming taught me many things. The one that transferred most directly to product engineering is the hash map pattern: instead of searching for something repeatedly, index it once and look it up in constant time.

The Problem It Solves

// O(N × M) — for each user, scan all logins
const activeUsers = users.filter(user =>
    recentLogins.some(login => login.userId === user.id)
);

// O(N + M) — build an index, then use it
const loginSet = new Set(recentLogins.map(l => l.userId));
const activeUsers = users.filter(user => loginSet.has(user.id));

The first version works fine for 100 users. With 10,000 users and 5,000 logins, it's 50 million comparisons. The second version is two linear passes.

Frequency Counting

Counting occurrences of something? Hash map.

const tagCounts = posts.reduce((acc, post) => {
    post.tags.forEach(tag => {
        acc[tag] = (acc[tag] ?? 0) + 1;
    });
    return acc;
}, {});
// { 'Laravel': 12, 'React': 8, 'Performance': 5 }

What would have been an N² nested loop is now a single linear pass.

Grouping Without Queries

// Group orders by customer without hitting the database again
const ordersByCustomer = orders.reduce((acc, order) => {
    acc[order.customerId] ??= [];
    acc[order.customerId].push(order);
    return acc;
}, {});

In Production Code

This pattern appears constantly in real applications. Building a permissions system? Map user IDs to permission sets. Deduplicating records? Set. Looking up config values in a loop? Map once, read many times.

The data structure choice isn't a competitive programming concern. It's an engineering concern that shows up every single day. Once you see the pattern, you can't unsee it.