go语言位操作库 — bitset

bitset库实现了bitsets数据结构,这是一种正整数和布尔值映射关系的结构,它比map[uint]bool更高效

 

什么是bitsets

bitsets基本思想是用一个bit位来标记某个元素对应的Value,每一位表示一个数,1表示存在,0表示不存在 比如我要表示1, 3, 7这3个数

  1. 构造一个空白bitsets:00000000
  2. 每位代表的值如下:76543210
  3. 想要表示的值标记1:10001010

有什么好处?

  最大的好处是节省存储空间,假设有20亿个正整数中找出m是否在其中 如果每个数字用int存储,占8byte,2000000000 * 8 = 14G 如果用bit存储每个数字,占1bit,2000000000 / 8 = 0.233G 由此可见bitsets节省了极大的存储空间

Usage

  安装

go get github.com/bits-and-blooms/bitset

基本操作

// 构造一个64bit长度的bitset
b := bitset.New(64)
// 放入一个数
b.Set(10)
fmt.Println(b.DumpAsBits()) // 000000000000000000000000000000000000000000000000010000000000
// 删除一个值
b.Clear(10)
fmt.Println(b.DumpAsBits()) // 000000000000000000000000000000000000000000000000000000000000
// 长度
b.Set(1).Set(3)
fmt.Println(b.Len()) // 64
// 测试
fmt.Println(b.Test(3)) // true
fmt.Println(b.Test(4)) // false

指定位置操作

b := &bitset.BitSet{}
b.Set(3)
// 在指定位置插入0
b.InsertAt(3)
fmt.Println(b.DumpAsBits()) // 000000000000000000000000000000000000000000000000000000010000
// 在指定位置修改
b.SetTo(4, false)
fmt.Println(b.DumpAsBits()) // 000000000000000000000000000000000000000000000000000000000000
// 指定位置删除
b.Set(3).DeleteAt(3) // 000000000000000000000000000000000000000000000000000000000000

 

两个bitsets交互

a := &bitset.BitSet{}
a.Set(1).Set(3).Set(5)
b := &bitset.BitSet{}
b.Set(3).Set(5).Set(7)
// 交集
fmt.Println(a.Intersection(b)) // {3,5}
// 并集
fmt.Println(a.Union(b)) // {1,3,5,7}
// 差集
fmt.Println(a.Difference(b)) // {1}
// 全等
fmt.Println(a.Equal(b)) // false

遍历

b := bitset.New(64)
b.Set(1).Set(3).Set(5).Set(7)
for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) {
    fmt.Println("The following bit is set:", i)
}
// The following bit is set: 1
// The following bit is set: 3
// The following bit is set: 5
// The following bit is set: 7

实例

假设现在数据库里有一个字段存储用户状态,设计是这样的:0 00 00 第1、2位表示会员等级 00表示普通会员,01表示vip1,10表示vip2,11表示svip 第3、4位表示头像状态 00表示未上传,01表示01审核中,10审核失败,11审核通过 第5位表示账号状状态 0表示正常,1表示封禁

b := bitset.New(5)
// 设置vip1,第1位0,第2位1
b.SetTo(1, false).SetTo(2, true)

// 设置头像审核失败,第3位1,第4位0
b.SetTo(3, true).SetTo(4, false)

// 状态初始化
b.ClearAll()

// 查看账号状态,第5位,true代表1 false代表0
b.Test(5) 

// 是不是svip,第1、2位是11
b.Test(1) && b.Test(2)

总结✦

bitset/bitmap在日常开发中会经常用到,在特定场景下有很好的效果。这个库可以简化操作bitset/bitmap的难度,而且这个库的源码也很好的演示了go的位操作

 

 

 

 

官方文档:https://github.com/bits-and-blooms/bitset

 

 

posted @ 2022-01-04 08:58  pebblecome  阅读(700)  评论(0编辑  收藏  举报