FixBitSet类在Lucene中属于一个工具类(Util),它的其中一个用途用来存储文档号,用一个bit位来描述(存储)一个文档号。该类特别适合存储连续并且没有重复的int类型的数值。最好情况可以用8个字节来描述64个int类型的值。下面通过介绍几个FixBitSet类的方法来理解这个类的存储原理。本篇文章纯属充数。。。直接看源码的话不会花很多时间,写这篇文章的原因主要是出于总结,因为好几个月前我看过了这个类的源码,今天准备写关于NumericDocValues的文章时再次遇到这个类时,发现又忘了,囧。
构造函数
1 | public FixedBitSet(int numBits) { |
构造一个FixedBitSet对象,参数numBits用来确定需要多少bit位来存储我们的int数值。如果我们另numBits的值为300,实际会分配一个64的整数倍的bit位。因为比300大的第一个64的倍数是 320 (64 * 5),所以实际上我们可以存储 [0 ~319]范围的数值。最终根据320的值,我们获得一个long类型的bit[]数组,并且bit[]数组初始化为大小5。在这里我们发现bit[]数组的每一个元素是long类型,即64bit,所以5个元素一共有 64 * 5 共 320个bit位。
void set(int index)方法
1 | public void set(int index) { |
例子:
图1:
添加 3
1 | 根据set()方法的逻辑: |
图2:
添加 67
1 | 根据set()方法的逻辑: |
图3:
添加 120
1 | 根据set()方法的逻辑: |
图4:
添加179、195、313
1 | 不赘述,大家可以自己算下是不是跟下图中一致。 |
图5:
通过上面的例子可以看到,如果我们存储的是连续的值,那么压缩率是很高的。当然同时可以看出无法处理有相同值的问题。
boolean get(int index)方法
get()方法可以实现随机访问,来确定index的值是否在bit[]数组中。
1 | public boolean get(int index) { |
结语
FixedBitSet类中还有一些其他的方法,比如说prevSetBit(int index)方法来找到第一个比index小的值和nextSetBit(int index)方法来找到第一个比index大的数,在Lucene中,常用FixedBitSet类来存储文档号,并且在通过prevSetBit(int index)或者nextSetBit(int index)来遍历文档号。
点击下载Markdown文档