Go 每日一库之 roaring

简介

集合是软件中的基本抽象。实现集合的方法有很多,例如 hash set、tree等。要实现一个整数集合,位图(bitmap,也称为 bitset 位集合,bitvector 位向量)是个不错的方法。使用 n 个位(bit),我们可以表示整数范围[0, n)。如果整数 i 在集合中,第 i 位设置为 1。这样集合的交集(intersection)、并集(unions)和差集(difference)可以利用整数的按位与、按位或和按位与非来实现。而计算机执行位运算是非常迅速的。

上一篇文章我介绍了bitset这个库。

bitset 在某些场景中会消耗大量的内存。例如,设置第 1,000,000 位,需要占用超过 100kb 的内存。为此 bitset 库的作者又开发了压缩位图库:roaring

本文首先介绍了 roaring 的使用。最后分析 roaring 的文件存储格式。

安装

本文代码使用 Go Modules。

创建目录并初始化:

$ mkdir -p roaring && cd roaring
$ go mod init github.com/darjun/go-daily-lib/roaring

安装roaring库:

$ go get -u github.com/RoaringBitmap/roaring

使用

基本操作

func main() {
  bm1 := roaring.BitmapOf(1, 2, 3, 4, 5, 100, 1000)
  fmt.Println(bm1.String())         // {1,2,3,4,5,100,1000}
  fmt.Println(bm1.GetCardinality()) // 7
  fmt.Println(bm1.Contains(3))      // true

  bm2 := roaring.BitmapOf(1, 100, 500)
  fmt.Println(bm2.String())         // {1,100,500}
  fmt.Println(bm2.GetCardinality()) // 3
  fmt.Println(bm2.Contains(300))    // false

  bm3 := roaring.New()
  bm3.Add(1)
  bm3.Add(11)
  bm3.Add(111)
  fmt.Println(bm3.String())         // {1,11,111}
  fmt.Println(bm3.GetCardinality()) // 3
  fmt.Println(bm3.Contains(11))     // true

  bm1.Or(bm2)                       // 执行并集
  fmt.Println(bm1.String())         // {1,2,3,4,5,100,500,1000}
  fmt.Println(bm1.GetCardinality()) // 8
  fmt.Println(bm1.Contains(500))    // true

  bm2.And(bm3)                      // 执行交集
  fmt.Println(bm2.String())         // {1}
  fmt.Println(bm2.GetCardinality()) // 1
  fmt.Println(bm2.Contains(1))      // true
}

上面演示了两种创建 roaring bitmap 的方式:

  • roaring.BitmapOf():传入集合元素,创建位图并添加这些元素

  • roaring.New():创建一个空位图

首先,我们创建了一个位图 bm1:{1,2,3,4,5,100,1000}。输出它的字符串表示,集合大小,检查 3 是否在集合中。

然后又创建了一个位图 bm2:{1,100,500}。输出检查三连。

接着创建了一个空位图 bm3,依次添加元素 1,11,111。输出检查三连。

然后我们对 bm1 和 bm2 执行并集,结果直接存放在 bm1 中。由于集合中的元素各不相同,此时 bm1 中的元素为{1,2,3,4,5,100,500,1000},大小为 8。

再然后我们对 bm2 和 bm3 执行交集,结果直接存放在 bm2 中。此时 bm2 中的元素为{1},大小为 1。

可以看出 roaring 提供的基本操作与 bitset 大体相同。只是命名完全不一样,在使用时需要特别注意。

  • bm.String():返回 bitmap 的字符串表示

  • bm.Add(n):添加元素 n

  • bm.GetCardinality():返回集合的基数(Cardinality),即元素个数

  • bm1.And(bm2):执行集合交集,会修改 bm1

  • bm1.Or(bm2):执行集合并集

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值