How to Implement a Bloom Filter from Scratch

What is a Bloom Filter?

Let's start with the core idea: a Bloom filter is a space-efficient data structure that answers one question—"Is this item definitely not in the set, or maybe in the set?" It never tells you "definitely yes." The "maybe" is where the trade-off lives.

Try it yourself:

We have a small bit array (10 slots) and 2 hash functions. Watch how adding words turns bits ON.

Status: Waiting for input...
Bit Array (0 = Off, 1 = On)
0 (Empty) 1 (Occupied)

Intuition: thinking about set membership

Imagine you're checking a very large dictionary for a word. You don't need the word's definition—just a quick "yes or no" on whether it exists. A traditional Set (like a hash table) would store every word exactly, using lots of memory. A Bloom filter uses a clever trick: it uses a bit array (just a long string of 0s and 1s) and a few different hash functions.

When you add a word, the hash functions compute several positions in that bit array and flip those bits to 1. When you check a word, the same hash functions compute positions. If any of those bits are 0, the word is definitely not in the set (because we would have set it to 1 when adding). If all the bits are 1, the word is maybe in the set—it could be a real match, or it could be that other words happened to set those same bits to 1. That's the false positive.

Real-world analogy

Think of a club with a secret handshake. The bouncer knows three specific moves (hash functions). When you join, you perform those three moves, and the bouncer makes a note in their notebook (sets three specific bits). Later, when someone claims to be a member, they perform the same three moves. If they fail any move, they're out—definitely not a member. If they nail all three, the bouncer says "maybe" and lets you in, because it's possible someone else happened to know those exact three moves by coincidence.

Common misconception: Bloom filters are deterministic

Some learners think a Bloom filter is like a mini-database that gives exact answers. This is wrong. Its power comes from being probabilistic. The "maybe" is a guaranteed feature, not a bug.

The guarantee is one-way: no false negatives. If the filter says "no," you can trust that absolutely. That's because we only ever set bits to 1; we never reset them to 0. So a 0 bit means "this item was never added." The "yes" (the "maybe") is always fuzzy. This asymmetry is what makes Bloom filters useful for filtering out obvious non-members before a costly full lookup (like querying a database or disk).

Why use a probabilistic data structure?

You might wonder: "Why would I ever use a data structure that isn't 100% correct?" The answer lies in two precious resources: memory and speed. In large-scale systems, you often don't need a perfect answer—you need a good enough answer, delivered instantly without draining your server's RAM.

The "Tuning Knob": Accuracy vs. Memory

Adjust the slider to change your desired False Positive Rate. Watch how the memory required for 1 million items changes.

High Error (10%) Low Error (0.01%)
Memory Required: ~1.2 MB

Based on storing 1,000,000 items.

Bit Array Size

Lowering the error rate forces the array to grow (more bits), reducing the chance of "collisions" (false positives).

Intuition: The "Net Mesh" Analogy

Think of a Bloom filter like a fishing net.

  • A coarse mesh (high false positive rate): The holes are big. It's very light and easy to carry (low memory), but it lets some fish slip through (false positives).
  • A fine mesh (low false positive rate): The holes are tiny. It catches everything, but the net is heavy, expensive, and harder to drag (high memory usage).

You choose the mesh based on your needs. If you're filtering spam emails, you might tolerate a coarse mesh (occasionally letting spam through to be deleted later). If you're filtering security tokens, you need a fine mesh.

The Space Savings

Storing 1 million items. Notice how the Bloom Filter stays small regardless of how complex the data is.

The "Gatekeeper" Workflow

The most common pitfall is treating a Bloom filter like a normal set. It is not a replacement; it is a gatekeeper.

1. User Query
2. Bloom Filter Check
3. Database (Only if "Maybe")

If the filter says "Definitely Not", you save a trip to the database. If it says "Maybe", you must check the database to be sure. This architecture is why systems like Cassandra, Redis, and Chrome (to block malicious URLs) rely on them.

Reality Check: The "Maybe" Trap

Never trust the "Maybe" blindly. False positives are rare, but they will occur. Your system design must always include a secondary, exact check (like a database lookup) for anything the filter says "Maybe" to.

Core concept: membership testing

At its heart, membership testing answers a simple question: "Is this specific item part of a stored set?" You see this everywhere—checking if a username exists in a database, if a URL is in a blocklist, or if a word is in a dictionary.

The Bloom Filter Twist

A standard set gives you a definitive YES or NO. A Bloom filter replaces that with a probabilistic answer: DEFINITELY NOT or MAYBE.

Try the Membership Check

We've already added "Apple" and "Banana" to this filter. Try checking for other words to see how the filter responds.

Enter a word to test membership...
Bit Array State (Pre-seeded)
0 (Empty) 1 (Occupied) Checked Bit

How it works (Step-by-Step)

To test if an item exists, we don't look for the item itself. We look for the traces it left behind. Here is the exact process:

  1. Hashing: We pass the item through our k hash functions.
  2. Indexing: Each hash function gives us a specific position (index) in the bit array.
  3. Inspection: We look at the bits at those positions.
def might_contain(item, bit_array, hash_functions):
    for hash_func in hash_functions:
        index = hash_func(item) % len(bit_array)
        # If we find a 0, the item was never added
        if bit_array[index] == 0:
            return False  # Definitely not present
    # If all bits are 1, it might be there
    return True  # Maybe present (could be false positive)

The "One-Sided Error" Property

This logic creates a fundamental asymmetry that defines the Bloom filter:

  • No False Negatives: If the filter says False ("definitely not"), you can trust it 100%. A 0 bit means "this specific slot has never been touched." If an item requires that slot to exist, and the slot is empty, the item simply isn't there.
  • Possible False Positives: If the filter says True ("maybe"), it might be wrong. Different items can map to the same bit positions, turning a 0 to 1 indirectly. This is the trade-off you configure.

Common Misconception: "Can it be wrong about a 'No'?"

Never. A Bloom filter never produces a false negative. The confusion often comes from the "maybe" answer. Because the "yes" is fuzzy, learners sometimes imagine the "no" might also be fuzzy. It is not. The design—only setting bits to 1—mathematically guarantees that if any required bit is 0, the item was never added. Period.

Intuition: The "Sieve" Analogy

Think of a Bloom filter like a sieve or a colander used for pasta.

  • The "No" (Holes): Anything that falls through the holes (hits a 0 bit) is definitely gone. It's not in the pot. You can discard it immediately.
  • The "Maybe" (Mesh): Anything that sits on the mesh (hits all 1 bits) might be pasta. It could be pasta, or it could be a piece of gravel that just happened to get stuck. You must pick it up and inspect it closely (a database lookup) to be sure.

This "definitely not" guarantee is gold for performance. You avoid expensive lookups for everything that falls through the sieve.

Choosing and implementing hash functions

Now we arrive at the engine room: hash functions. A Bloom filter isn't magic; it's math. Specifically, it relies on k independent hash functions to distribute your data across the bit array.

The "Independent Sprinklers" Analogy

Imagine you are watering a long garden bed (the bit array). You have k sprinklers (hash functions).

  • Independent Sprinklers: Each sprinkler sprays water at a random, distinct location. This ensures the whole bed gets wet evenly.
  • Dependent Sprinklers: If all your sprinklers are connected to the same pipe and just shifted slightly, they will spray the same few spots over and over. This leaves large dry patches (unused bits) and creates soggy clumps (collisions).

Visualizing Hash Distribution

Add words to see how different hashing strategies fill the bit array.

Independent Hashes (Good)

Uses distinct, random indices for each hash function.

Bits set: 0
Offset Hashing (Bad)

Uses `hash(x) + i`. Creates clumps!

Bits set: 0

The "Single Hash" Pitfall

A common beginner mistake is to think: "I only need one hash function, I'll just add 1, 2, and 3 to the result to get the other indices."

// ❌ WRONG: This creates clumps!
def bad_hash(item, i):
    return hash(item) + i  # Just shifts the same pattern

As you saw in the simulation above, this creates clumping. If the base hash lands on index 2, your three indices are 2, 3, and 4. You are filling up the array in little bands. This dramatically increases false positives because unrelated items are likely to overlap in these predictable bands.

Practical Implementation: Double Hashing

So, how do we get multiple independent hashes without running a heavy cryptographic algorithm five times? We use a trick called Double Hashing.

We compute two base hashes, h1 and h2. Then, we generate the i-th hash function using this formula:

h(i) = (h1 + i * h2) % m

This mathematically approximates independence. h2 acts as a "step size" that changes for every item, spreading the indices out across the array m.

# ✅ CORRECT: Double Hashing
def get_indices(item, k, m, h1, h2):
    indices = []
    for i in range(k):
        # Linear combination of two base hashes
        idx = (h1(item) + i * h2(item)) % m
        indices.append(idx)
    return indices

Speed vs. Security

Don't use SHA-256. It's too slow. For Bloom filters, you want speed. Functions like MurmurHash3 or xxHash are the industry standard because they are lightning fast and have excellent "avalanche" properties (small input change = big output change).

Understanding false positive rate

We've established that a Bloom filter can say "maybe" when the answer is actually "no." The False Positive Rate (FPR) is simply the probability that this happens. It quantifies the chance of a wrong yes.

The Mathematical Reality

You don't need to be a mathematician to understand the formula, but you should know the variables. The FPR depends on three things:

  • m: The size of your bit array (how many coins you have).
  • n: The number of items you add (how many times you flip coins).
  • k: The number of hash functions (how many coins you flip per item).

The Formula

FPR ≈ (1 - e-kn/m)k

(This assumes a large array and uniform hashing)

Intuition: The Coin Flip Game

Let's make this concrete. Imagine a table full of coins (the bit array).

  • Initial State: All coins are Tails (0).
  • Adding an Item: You flip k random coins to Heads (1).
  • Checking an Item: You check k specific coins. If all are Heads, you say "Maybe." If even one is Tails, you say "Definitely Not."

A False Positive happens when a new item (one you never added) happens to check k coins that were flipped to Heads by other items.

Simulate False Positives

Step 1: Add some items to fill the array.
Step 2: Check a "New Item" (one that was never added).
Watch out for False Positives!

Start by adding items...
The Bit Array (Coins)
Tails (0) Heads (1) Checked

How to calculate the optimal settings

You rarely compute the FPR formula by hand at runtime. Instead, you use it during the design phase. If you know you plan to store n items and you have a memory budget of m bits, you can calculate the optimal number of hash functions to minimize errors:

koptimal = (m / n) × ln(2)

This tells you the "sweet spot." If you use fewer hash functions than this, you waste space. If you use more, you fill the array too fast and increase false positives.

Common Misconception: "False Positives are Rare"

"Rare" is not a guarantee—it is a configuration. If you pick your array size m arbitrarily, your FPR could be 30%, 50%, or even higher. Always calculate your FPR based on your expected data volume. A Bloom filter with poor parameters can be worse than useless because it gives you a false sense of security.

Designing the algorithm

Now that we understand the theory, let's build the engine. Designing a Bloom filter is surprisingly simple because it relies on just two core operations: adding an item and checking for an item.

Algorithm design steps

Imagine you are setting up a giant chalkboard (the bit array). It's your only memory. You have a set of distinct chalks (hash functions).

Visualize the "Add" Operation

Type a word. We will use 2 hash functions to find 2 positions in the array and set those bits to 1.

Status: Ready to add...
Bit Array (Size: 8)
0 (Empty) 1 (Occupied)

Step-by-step mental model

Here is the logic you need to implement in your code. Notice how clean it is.

Step 1: Add add(item)

  1. Loop through each of your k hash functions.
  2. Compute the index: index = hash(item) % size.
  3. Set bit_array[index] = 1.
  4. Done. You never store the item itself.

Step 2: Check might_contain(item)

  1. Loop through each of your k hash functions.
  2. Compute the index: index = hash(item) % size.
  3. If bit_array[index] == 0, return False immediately.
  4. If all checks pass, return True (maybe).

This logic translates directly into Python code. Notice the simplicity:

def add(self, item):
    # For every hash function we have...
    for i in range(self.num_hashes):
        # Get a hash value, modulo the array size
        index = self._hash(item, i) % self.size
        # Turn the bit ON
        self.bit_array[index] = 1

def might_contain(self, item):
    for i in range(self.num_hashes):
        index = self._hash(item, i) % self.size
        # If we find a single 0, the item is NOT here
        if self.bit_array[index] == 0:
            return False
    # If we see only 1s, it MIGHT be here
    return True

Common Pitfall: Off-by-one errors

The Modulo Trap: Hash functions can sometimes return negative numbers (in languages like Java or C++) or numbers larger than your array size. Always wrap your hash result in a modulo operation: hash_value % self.size. Without this, you will crash your program or corrupt memory.

Algorithm complexity analysis

Why is this so popular? It's all about efficiency.

O(k)
Time Complexity

Since k (number of hashes) is a small constant (e.g., 3 to 10), this is effectively O(1). It doesn't matter if you have 10 items or 10 billion items; checking takes the same tiny amount of time.

O(m)
Space Complexity

You only store m bits. You don't store the actual data (strings, objects, etc.). This makes it incredibly compact compared to a Hash Set.

Implementing a Bloom Filter Data Structure

Theory is great, but code is where the magic happens. Let's build a Bloom filter from scratch. We will implement the three core steps: Creating the array, Adding items, and Checking membership.

Professor's Tip

A Bloom filter is incredibly simple. It's just an array of bits and a loop. The complexity is hidden in the math of choosing the right size, but the code is straightforward.

Live Implementation Demo

Step 1: Initialize the filter (create the bit array).
Step 2: Add words to "write" to the array.
Step 3: Check words to see if they "exist".

System ready. Initialize the filter to begin.
Bit Array (Size: 10)
0 (Empty) 1 (Occupied) Checked

Step 1: Create Bit Array

The foundation is the bit array. In Python, this is just a list of integers (0s). In languages like C or Java, this might be a byte array or a `BitSet`. The key is that every single bit must start at 0.

def __init__(self, size, num_hashes):
    self.size = size
    self.num_hashes = num_hashes
    # All bits start at 0. This is critical!
    self.bit_array = [0] * size

Step 2: Add Elements (Insert)

When you add an item, you don't store the item itself. You calculate k indices using your hash functions and flip the bits at those positions to 1.

def add(self, item):
    for i in range(self.num_hashes):
        # Calculate index using hash function i
        index = self._hash(item, i) % self.size
        # Set the bit to 1
        self.bit_array[index] = 1

Step 3: Check Membership (Query)

This is the most critical part. You re-calculate the same k indices.

  • If any of the bits at those indices is 0, you can immediately return False. The item was never added.
  • If all bits are 1, you return True (meaning "Maybe").
def might_contain(self, item):
    for i in range(self.num_hashes):
        index = self._hash(item, i) % self.size
        # If we find a single 0, it's definitely NOT here
        if self.bit_array[index] == 0:
            return False
    # If we see only 1s, it MIGHT be here
    return True

Common Mistake: Forgetting to Initialize

Why it's critical: In some low-level languages (like C or C++), allocating memory doesn't automatically set it to zero. It might contain "garbage" data (random 1s). If your array starts with random 1s, your "Definitely Not" guarantee breaks immediately because you'll have false positives from the very first check.

The Fix: Always explicitly initialize your array. In Python, [0] * size is safe. In C, use calloc or a loop to zero it out.

Space-efficient data structures

Now we arrive at the "killer feature" of Bloom filters: Space Efficiency. Why would a system choose a probabilistic structure over a standard one? The answer is almost always memory.

The Memory Showdown

Compare how much memory is needed to store the same set of data.

Deterministic Hash Set

Stores the actual data. If the data is huge, memory usage grows linearly with item size.

"Apple" ~50 bytes
"Banana" ~50 bytes
"Cherry" ~50 bytes
Total: ~150+ bytes

Probabilistic Bloom Filter

Stores only bits. The size of the item doesn't matter. We just flip switches.

Total: ~10 bits
The Insight: A Bloom filter compresses the entire set into a fixed-size "sketch." You trade the storage of the item itself for a few bits of memory. For large datasets (like millions of URLs), this compression is massive—often 10x to 100x smaller than a standard hash table.

Intuition: Compressing Information

Think of a Bloom filter like a crowd-sourced fingerprint.

In a Hash Set, every person (item) gets their own locker (memory address) to store their identity. In a Bloom filter, everyone just leaves a mark on a giant shared wall. If you see a mark, you know someone was there. Because many people leave marks on the same spots (collisions), the wall stays relatively small compared to the number of people.

The cost? Sometimes a new person looks at the wall, sees marks that weren't made by them, and thinks "Oh, I must have been here." That's the false positive. But the wall (memory) stays tiny.

The Tuning Knob: Space vs. Accuracy

Adjust the bit array size to see how it affects your False Positive Rate.

Items (n): 1,000,000
Small (4MB) Large (16MB)
False Positive Rate: ~0.1%

Lower is better, but costs more memory.

Visualizing Bit Density

As you increase the array size, the bits become more sparse (less crowded), reducing the chance of accidental collisions.

The Trade-off Formula

The relationship between space ($m$), items ($n$), and error ($p$) is governed by this formula:

m ≈ - (n × ln(p)) / (ln(2))2

This tells us that to halve your error rate, you need to add a fixed number of bits per item. You don't need to memorize the math, but you should understand the curve:

  • Diminishing Returns: Dropping the error from 10% to 1% is cheap. Dropping it from 0.01% to 0.001% requires a massive increase in memory.
  • Design Phase: You usually decide your budget (e.g., "I have 500MB RAM") and your acceptable error (e.g., "I can tolerate 1% mistakes") before you build.

Professor's Rule of Thumb

A standard Bloom filter usually uses about 9.6 bits per item to achieve a 1% false positive rate. If you have 1 million items, you need roughly 9.6 million bits, or about 1.2 MB of RAM. That's incredibly cheap!

When to Choose Bloom Filters

Bloom filters aren't a magic bullet for everything. They are a specialized tool for specific scenarios.

Use When...

  • Memory is tight: You have millions of items and can't afford a Hash Set.
  • False positives are okay: You can afford a "false alarm" as long as you check the source of truth later.
  • Speed is key: You need to filter out bad requests instantly before hitting a database.

Avoid When...

  • Zero errors allowed: If a false positive causes a crash or security breach, don't use it.
  • You need to delete items: Standard Bloom filters don't support deletion (without complex variants).
  • You need to list items: You cannot iterate over a Bloom filter to see what's inside.

In summary, a Bloom filter is a pre-filter. It's the bouncer at the club who checks the list. If you're not on the list (Definitely Not), you go home. If you are on the list (Maybe), you get to talk to the manager (Database) to prove you're real.

Advanced considerations

You now have a working Bloom filter. But in production, you need to tune it. We are moving from "How it works" to "How to make it perfect for your specific data."

1. The Golden Rule: Choosing optimal hash functions

The number of hash functions, k, is your most powerful tuning knob.
Too few? You leave too many bits as 0, wasting space.
Too many? You fill the array too fast, causing false positives.
Just right? You minimize the error rate for your memory budget.

The Math Behind the Magic

Calculus tells us the optimal k occurs when:

koptimal = (m / n) × ln(2)

Where m is bit array size and n is expected items.

Recommended k: 7
Est. False Positive Rate: 0.12%

Visualizing Bit Density (m bits)

As you add more items (n) relative to size (m), the grid fills up, increasing the chance of accidental collisions.

import math

def optimal_k(m, n):
    # m = bit array size, n = expected items
    # ln(2) is approx 0.693
    return max(1, int(round((m / n) * math.log(2))))

2. Dynamic Resizing: What if you run out of space?

Standard Bloom filters are static. If you add more items than n, your error rate skyrockets. You cannot simply "resize" the array because you don't store the original items to re-hash them.

The Solution: Scalable Bloom Filters

Instead of one giant filter, use a chain of smaller filters. When the current filter gets too full (too many 1s), you allocate a new, larger filter and start adding items there.

Filter 1 (Full)
New Items
Filter 2 (Empty)

How it works: When checking an item, you query Filter 1. If it's not there, you query Filter 2, then Filter 3, and so on.

3. Concurrency: Handling multiple threads

In a multi-threaded environment, two threads might try to set the same bit at the exact same time. While setting a bit to 1 is generally safe (idempotent), the underlying read-modify-write operation must be atomic.

Non-Atomic Write

Thread A reads bit (0). Thread B reads bit (0).

Thread A writes 1. Thread B writes 1.

Result: Data integrity is fine, but in languages like C/Java, you might lose updates or see inconsistent states without locks.

Atomic Bitwise OR

Use hardware-level atomic operations.

bit |= (1 << offset)

Result: Guaranteed safe updates without heavy locking.

Practical Implementation

To make a Bloom filter thread-safe, treat the bit array as an array of Atomic Words (e.g., 64-bit integers). When setting a bit, you perform an atomic bitwise OR on that specific word.

// Java-like pseudocode for Atomic Add
void add(Item item) {
    for (int i = 0; i < numHashes; i++) {
        int index = hash(item, i) % size;
        int wordIndex = index / 64; // Which 64-bit word?
        int bitOffset = index % 64; // Which bit in that word?

        // Atomically set the bit without locking the whole array
        bitArray.getAndUpdate(wordIndex, word -> word | (1L << bitOffset));
    }
}

You've built the filter, tuned the math, and understood the trade-offs. Now, let's address the questions that come up in real-world engineering.

What is a bloom filter used for in practice?

You use a Bloom filter when you need a fast, memory-cheap way to rule out "definitely not" before a slower, exact check.

Common Patterns

  • Database/network caches: Filter out queries for keys that don't exist.
  • Distributed systems: Check if a peer might have data (e.g., Cassandra, Bitcoin).
  • Spell checkers: Test if a word is possibly valid.
  • Web crawlers: Avoid re-crawling URLs already seen.
  • Security: Pre-filter blocklists (IPs, URLs).

Key Rule: It's a pre-filter, never a standalone solution. Always pair it with an exact data store for the "maybe" cases.

Why does my bloom filter give false positives?

False positives happen because bits are shared. When you add an item, you set k bits to 1. Different items can set overlapping bits. A new, unadded item might accidentally hit k bits that were all set by other items.

This isn't a bug—it's the designed trade-off. You control the rate via:

  • Bit array size m: Larger m spreads bits thinner, lowering collisions.
  • Number of hashes k: More hashes make each item set more bits, increasing density.

Diagnosis: If your false positive rate is higher than expected, you likely have too small m for your n, or poorly distributed hash functions.

Can I delete elements from a bloom filter?

No, not in the standard version. Once a bit is set to 1, it stays 1 forever. Deleting an item would require clearing its bits, but those bits might also be set by other items.

Visualizing the "Deletion Trap"

Standard Bloom Filter (Bits)
1
1
0

Item A (indices 0,1) & Item B (index 1) are added.

Click button to see result...
Counting Bloom Filter (Counters)
1
2
0

Item A adds +1, Item B adds +1. Index 1 has count 2.

Click button to see result...

Workarounds: If you need deletion, use a Counting Bloom Filter (stores small integers instead of bits) or a Scalable Bloom Filter (chain of filters).

How many hash functions should I use?

Use the optimal k derived from your bit array size m and expected item count n:

koptimal = (m / n) × ln(2) ≈ 0.693 × (m / n)

Intuition: If m is large (sparse array), you can use more hashes. If m is close to n (dense array), use fewer hashes.

Practical Tip: Calculate k_optimal during design. If m/n = 10, k ≈ 7. Never guess—use the formula.

Is a bloom filter suitable for large data streams?

Yes, but with caveats. Bloom filters excel for streaming data because they use fixed memory and have O(1) insertions.

  • Limitation: False positive rate increases as more items n are added beyond your design estimate.
  • No deletions: If items expire, you can't remove them (unless using a counting variant).

For high-volume streams, use a Scalable Bloom Filter (multiple filters with increasing sizes) or periodically reset if old data becomes irrelevant.

What are the security implications of using a bloom filter?

The main risk is adversarial false positives. An attacker who knows your hash functions can craft items to deliberately cause collisions or exhaust the filter.

Mitigations

  • Use secret hash seeds: Initialize hash functions with a random seed unknown to the attacker.
  • Universal hashing: Choose hash functions from a universal family randomly at startup.
  • Combine with other checks: Never rely solely on a Bloom filter for security. Always follow a "maybe" with an exact check.

How does the false positive rate affect memory usage?

There's a direct trade-off: lower false positive rate requires a larger bit array m.

FPR ≈ (1 - e-kn/m)k

For a fixed n, halving the FPR roughly requires doubling m.

Example: 1 Million Items

  • FPR = 1% → ~1.2 MB RAM
  • FPR = 0.1% → ~1.8 MB RAM

Design Process: Choose acceptable FPR first, calculate required m, then compute optimal k.

Can I use a bloom filter for approximate counting?

Not directly. A standard Bloom filter only answers membership (is this item possibly in the set?). It doesn't tell you how many items are in the set.

  • Counting Bloom filter: Replace bits with small counters (e.g., 4-bit). Increment on add, decrement on delete. You can estimate set size by summing counters, but beware of overcounting.
  • HyperLogLog: For cardinality estimation only (no membership), with very low memory.

Bottom line: If you need both membership and counts, consider a counting Bloom filter. For membership only, stick with the standard version.

Post a Comment

Previous Post Next Post