实现了布隆过滤器,布隆过滤器不加锁,同时改善了之前实现的数据结构中出现的一些错误

This commit is contained in:
hlccd 2021-12-27 16:40:40 +08:00 committed by GitHub
parent 6e3d23e60a
commit fb0b93e0ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 143 additions and 9 deletions

View File

@ -11,7 +11,6 @@ package bitmap
//bitmap位图结构体
//包含其用于存储的uint64元素切片
//选用uint64是为了更多的利用bit位
type Bitmap struct {
bits []uint64
}
@ -19,7 +18,6 @@ type Bitmap struct {
//bitmap位图容器接口
//存放了bitmap容器可使用的函数
//对应函数介绍见下方
type bitmaper interface {
Insert(num uint) //在num位插入元素
Delete(num uint) //删除第num位
@ -105,14 +103,14 @@ func (bm *Bitmap) Delete(num uint) {
//从后往前遍历判断可缩容内容是否小于总组数
i := len(bm.bits) - 1
for ; i >= 0; i-- {
if bm.bits[i] == 0 && i!=len(bm.bits)-256{
if bm.bits[i] == 0 && i != len(bm.bits)-256 {
continue
} else {
//不为0或到1024个时即可返回
break
}
}
if i <= len(bm.bits)/2 || i==len(bm.bits)-256 {
if i <= len(bm.bits)/2 || i == len(bm.bits)-256 {
//小于总组数一半或超过1023个,进行缩容
bm.bits = bm.bits[:i+1]
}
@ -129,7 +127,7 @@ func (bm *Bitmap) Delete(num uint) {
// 否则判断第num为是否为1,为1返回true,否则返回false
//@receiver bm *Bitmap 接受者bitmap的指针
//@param num int 待检测位的下标
//@return b bool 第num位存在于位图中
//@return b bool 第num位存在于位图中吗?
func (bm *Bitmap) Check(num uint) (b bool) {
//bm不存在时直接返回false并结束
if bm == nil {
@ -156,7 +154,7 @@ func (bm *Bitmap) Check(num uint) (b bool) {
//@return nums []uint 所有在位图中存在的元素的下标集合
func (bm *Bitmap) All() (nums []uint) {
//对要返回的集合进行初始化,以避免返回nil
nums=make([]uint,0,0)
nums = make([]uint, 0, 0)
//bm不存在时直接返回并结束
if bm == nil {
return nums
@ -179,7 +177,7 @@ func (bm *Bitmap) All() (nums []uint) {
// 清空位图
//@receiver bm *Bitmap 接受者bitmap的指针
//@param nil
//@return nums []uint 所有在位图中存在的元素的下标集合
//@return nil
func (bm *Bitmap) Clear() {
if bm == nil {
return

View File

@ -1 +1,137 @@
package bloomFilter
//@Title bloomFilter
//@Description
// bloomFilter布隆过滤器容器包
// 内部使用uint64切片进行存储
// 将任意类型的值进行hash计算后放入布隆过滤器中
// 可用于查找某一值是否已经插入过,但查找存在误差,只能确定其不存在,不能保证其必然存在
// 不能用于删除某一特定值,但可清空整个布隆过滤器
import "fmt"
//bloomFilter布隆过滤器结构体
//包含其用于存储的uint64元素切片
//选用uint64是为了更多的利用bit位
type bloomFilter struct {
bits []uint64
}
//bloomFilter布隆过滤器接口
//存放了bloomFilter布隆过滤器可使用的函数
//对应函数介绍见下方
type bloomFilteror interface {
Insert(v interface{}) //向布隆过滤器中插入v
Check(v interface{}) (b bool) //检查该值是否存在于布隆过滤器中,该校验存在误差
Clear() //清空该布隆过滤器
}
//@title hash
//@description
// 传入一个虚拟节点id和实际结点
// 计算出它的hash值
// 逐层访问并利用素数131计算其hash值随后返回
//@receiver nil
//@param v interface{} 待计算的值
//@return h uint64 计算得到的hash值
func hash(v interface{}) (h uint64) {
h = uint64(0)
s := fmt.Sprintf("v", v)
bs := []byte(s)
for i := range bs {
h += uint64(bs[i]) * 131
}
return h
}
//@title New
//@description
// 新建一个bloomFilter布隆过滤器容器并返回
// 初始bloomFilter的切片数组为空
//@receiver nil
//@param nil
//@return bf *bloomFilter 新建的bloomFilter指针
func New() (bf *bloomFilter) {
return &bloomFilter{
bits: make([]uint64, 0, 0),
}
}
//@title Insert
//@description
// 以bloomFilter布隆过滤器容器做接收者
// 先将待插入的value计算得到其哈希值hash
// 再向布隆过滤器中第hash位插入一个元素(下标从0开始)
// 当hash大于当前所能存储的位范围时,需要进行扩增
// 若要插入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64
// 否则则直接增加到可以容纳第hash位的位置,以此可以提高冗余量,避免多次增加
//@receiver bf *bloomFilter 接收者bloomFilter指针
//@param v interface{} 待插入的值
//@return nil
func (bf *bloomFilter) Insert(v interface{}) {
//bm不存在时直接结束
if bf == nil {
return
}
//开始插入
h := hash(v)
if h/64+1 > uint64(len(bf.bits)) {
//当前冗余量小于num位,需要扩增
var tmp []uint64
//通过冗余扩增减少扩增次数
if h/64+1 < uint64(len(bf.bits)+1024) {
//入的位比冗余的多不足2^16即1024*64时,则新增1024个uint64
tmp = make([]uint64, len(bf.bits)+1024)
} else {
//直接增加到可以容纳第num位的位置
tmp = make([]uint64, h/64+1)
}
//将原有元素复制到新增的切片内,并将bm所指向的修改为扩增后的
copy(tmp, bf.bits)
bf.bits = tmp
}
//将第num位设为1即实现插入
bf.bits[h/64] ^= 1 << (h % 64)
}
//@title Check
//@description
// 以bloomFilter布隆过滤器容器做接收者
// 将待查找的值做哈希计算得到哈希值h
// 检验第h位在位图中是否存在
// 当h大于当前所能存储的位范围时,直接返回false
// 否则判断第h为是否为1,为1返回true,否则返回false
// 利用布隆过滤器做判断存在误差,即返回true可能也不存在,但返回false则必然不存在
//@receiver bf *bloomFilter 接收者bloomFilter指针
//@param v interface{} 待查找的值
//@return b bool 待查找的值可能存在于布隆过滤器中吗?
func (bf *bloomFilter) Check(v interface{}) (b bool) {
//bf不存在时直接返回false并结束
if bf == nil {
return false
}
h := hash(v)
//h超出范围,直接返回false并结束
if h/64+1 > uint64(len(bf.bits)) {
return false
}
//判断第num是否为1,为1返回true,否则为false
if bf.bits[h/64]&(1<<h%64) > 0 {
return true
}
return false
}
//@title Clear
//@description
// 以bloomFilter布隆过滤器容器做接收者
// 清空整个布隆过滤器
//@receiver bf *bloomFilter 接收者bloomFilter指针
//@param nil
//@return nums []uint 所有在位图中存在的元素的下标集合
func (bf *bloomFilter) Clear() {
if bf == nil {
return
}
bf.bits = make([]uint64, 0, 0)
}

View File

@ -61,7 +61,7 @@ type consistentHasher interface {
//@receiver nil
//@param id int 虚拟节点的id
//@param v interface{} 实际结点的key
//@return hm *hashMap 计算得到的hash值
//@return h uint32 计算得到的hash值
func hash(id int, v interface{}) (h uint32) {
prime := primes[(id*id+len(primes))%len(primes)]
h = uint32(0)