Golang布隆过滤器升级版

发布时间 2023-11-11 20:33:45作者: 辉辉、

作用:平常使用的布隆过滤器可以用来过滤Redis空数据,避免缓存穿透。

升级点:将原本的bool数组位更改为int数组,实现便于删除操作的场景。
代码如下:

package main

import (
	"fmt"
)

// BloomFilter 布隆过滤器
type BloomFilter struct {
	bitArray []int //升级版结构 哈希所落位置+1
	hashNum  int   //哈希的数量
}

func NewBloomFilter(bitArray, hashNum int) *BloomFilter {
	return &BloomFilter{
		hashNum:  hashNum,
		bitArray: make([]int, bitArray),
	}
}

// 哈希当前元素
func (t *BloomFilter) hash(value string, seed int) int {
	var result = 0
	for i := 0; i < len(value); i++ {
		result = result*seed + int(value[i])
	}
	//length = 2^n 时,X % length = X & (length - 1)
	return result & (t.hashNum - 1)
}

// 追加哈希布隆过滤器
func (t *BloomFilter) add(item string) {
	//哈希当前元素
	for i := 0; i < t.hashNum; i++ {
		//追加当前哈希数量
		idx := t.hash(item, i) % len(t.bitArray)
		t.bitArray[idx]++
	}
}

// 删除哈希布隆过滤器
func (t *BloomFilter) delete(item string) {
	for i := 0; i < t.hashNum; i++ {
		//出现落空直接返回不存在
		idx := t.hash(item, i) % len(t.bitArray)
		if t.bitArray[idx] > 0 {
			t.bitArray[idx]--
		}
	}
}

// 判断元素是否在布隆过滤器
func (t *BloomFilter) contains(item string) bool {
	for i := 0; i < t.hashNum; i++ {
		//出现落空直接返回不存在
		idx := t.hash(item, i) % len(t.bitArray)
		if t.bitArray[idx] == 0 {
			return false
		}
	}
	return true
}

func main() {
	bf := NewBloomFilter(26, 5)

	//追加元素
	bf.add("测试")
	bf.delete("测试")
	bf.add("哈哈")
	bf.delete("哈哈")

	fmt.Println(bf.contains("测试"))
	fmt.Println(bf.contains("哈哈"))
	fmt.Println(bf.bitArray)
}