3.4         Lucene工具箱之OpenBitSet

在Lucene中,DocId具有这样的特征:唯一/递增。而且在搜索的过程,不同term之间的DocId集合进行逻辑运算的需求非常之多。OpenBitSet正是集合运算的利器。

3.4.1             OpenBitSet的原理

假设有一个byte,一共有8个二进制位,如下图:

0

0

0

0

0

0

0

0

7

6

5

4

3

2

1

0

如果每个二进制位表示一个数,这个Byte可以存储[0,7]共8个数。

比如存储4,6这两个数,则byte中各个二进制位的状态如下:

0

1

0

1

0

0

0

0

7

6

5

4

3

2

1

0

用二进制位的下标表示存储的数,并在将二进制位的相应状态设为1。OpentBitSet正是利用上述原理来存储数据。

3.4.2 OpenBitSet的简单应用

假设有两个集合A = {1,3,4,10,5},B={5,3,2,8}。计算A集合与B集合的并集;计算A集合与B集合的交集。

int[] a = {1,3,4,10,5};

int [] b = {5,3,2,8};

OpenBitSet setA = new OpenBitSet();

for(int i : a) setA.set(i);

OpenBitSet setB = new OpenBitSet();

for(int i : b) setB.set(i);

OpenBitSet unionSet = setA.clone();

unionSet. union(setB); //取A与B的并集

DocIdSetIterator iterator = unionSet.iterator();

while(iterator.nextDoc()!=DocIdSetIterator.NO_MORE_DOCS){

System.out.print(iterator.docID()+", ");

}System.out.println();

OpenBitSet intersectionSet = setA.clone();

intersectionSet. intersect(setB);//取A与B的交集

iterator = intersectionSet.iterator();

while(iterator.nextDoc()!=DocIdSetIterator.NO_MORE_DOCS){

System.out.print(iterator.docID()+", ");

}System.out.println();

输出结果如下:

并集:1, 2, 3, 4, 5, 8, 10,

交集:3, 5,

3.4.3 OpenBitSet的源码分析

OpenBitSet利用二进制位来存储数据,一个long类型最高只有64位,能存储63个数。

如果存储[0,63]之间的数,需要1个long类型串联起来。

如果存储[0,127]之间的数,需要2个long类型串联起来。

如果存储[0,191]之间的数,需要3个long类型串联起来。

……

如果存储[0,(64N+m)] (N,m为非负整数,m<64)之间的数,需要N个long类型串联起来.

所以OpenBitSet的核心就是一个long类型的数组bits。

public class OpenBitSetextendsDocIdSet implements Bits, Cloneable {

protectedlong[]bits;

这个数组需要开多大呢?依据存储数据的最大值而定。OpenBitSet有构造函数如下:

publicOpenBitSet() {

this(64);

}

这个构造函数调用了另一个需要传参的构造函数:

/** Constructs an OpenBitSet large enough to hold <code>numBits</code>.

*/

publicOpenBitSet(long numBits) {

this.numBits = numBits;

bits = new long[bits2words(numBits)];

wlen= bits.length;

}

该构造函数中调用了bits2words()方法来通过传入的参数计算bits数组的大小。

tits2words(64) = 1;表示存储[0,63]之间的数需要1个long类型。

tits2words(256)=2;表示需要存储[0,255]之间的数需要2个long类型。

依此类推……

这样传参避免我们人工计算bits数组的大小,也封装了实现原理。

OpenBitSet的数据存储

首先要清楚的是,在OpenBitSet中:

[0,63]存储在bits[0]的64个位中

[64,127]存储在bits[1]的64个位中

……

[64N,64N+63]存储在bits[N]的64个位中

任何一个非负整数,都可以表示成:64*N+m (N,m都是非负整数,m<64)。其中N表示bits数组的下标,m表示bits[N]的64个位中需要把状态置为1的二进制位的下标。

存储数据的原代码如下:

/** sets a bit, expanding the set size if necessary */

publicvoidset(longindex) {

int wordNum = expandingWordNum(index);

int bit = (int)index & 0x3f;

long bitmask = 1L << bit;

bits[wordNum] |= bitmask;

}

整个set方法有4句代码,我们一句一句分析:

第1句代码求公式64*N+m中的N。参数index除以64或者 index>>6就可以了。左移6位即除以2^6=64.

第2句代码求公式64*N+m中的m。注意0x3f= 64 =(111111)2,index%64 即为 index & 0x3f 。

第3句和第4句即把bits[N]的第m位设置为1。

    最后总结一下OpenBitSet数据存储的特点:OpenBitSet无法存储重复的数据。数据存储到OpenBitSet中后就是有序的了。OpenBitSet适合存储密集程度高,且量大的数据。OpenBitSet中存储的数据适合位运算,比如取交集、并集、补集……

由于直接从word中粘贴来受到了长度的限制,我又不想在博客编辑器中重新写一遍,所以关于OpenBitSetIterator相关的内容和Lucene4.2的其它细节可以从我的《Lucene4.x源码解读》第4章4.3节中了解。OpenBitSetIterator分析了bitList的实现原理。

《Lucene4.x源码解读》会不定时更新,可以关注我的新浪微博 @帅广应s 。

转载于:https://blog.51cto.com/sbp810050504/1567796

Lucene工具箱之OpenBitSet(一)相关推荐

  1. 【Java】Lucene检索引擎详解

    基于Java的全文索引/检索引擎--Lucene Lucene不是一个完整的全文索引应用,而是是一个用Java写的全文索引引擎工具包,它可以方便的嵌入到各种应用中实现针对应用的全文索引/检索功能. L ...

  2. Lucene学习总结之七:Lucene搜索过程解析

    一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...

  3. lucene搜索引擎总结

    <p>Lucene分析器---Analyzer主要包括分词器和过滤器两种组件</p><p>分词器主要作用是对传入的文本进行切分,将文本按规则切分为一个个可以进入索引 ...

  4. Lucene4.10使用教程(六):Lucene的过滤器

    过滤器在生产环境中应用也比较多.比如禁用词的过滤显示.推荐商品的过期设置等. 在编写时,需要在incrementToken添加自己的过滤规则.,下面的demo是针对同义词编写的过滤.过滤器的编写也可以 ...

  5. Lucene in Action中文版

    Lucene in Action 中文版  第一部分 Lucene核心 1.      接触Lucene  2.      索引 3.      为程序添加搜索 4.      分析 5.      ...

  6. Lucene In Action 中文版 [1]

    jimoxing写在前面的话:本人整理此书发表在CSDN,不做任何商业用途,完全本着为人民服务. 请转载的各位加上访问地址:http://blog.csdn.net/jimoxing2009/arti ...

  7. Lucene in Action 中文版

    Lucene in Action 中文版 ERIK HATCHER OTIS GOSPODNETIC zw_ren译 主要内容 第一部分 Lucene核心 1.      接触Lucene 2.    ...

  8. Lucene in Action(简体中文版)

    共10部分 第一部分 Lucene核心[code="java"][/code] 1. 接触Lucene 2. 索引 3. 为程序添加搜索 4. 分析 5. 高极搜索技术 6. 扩展 ...

  9. 工具箱支持汽车质量人工智能

    工具箱支持汽车质量人工智能 Toolkit supports automotive-quality AI NXP半导体公司推出了一个新的深度学习工具包,叫做eIQ Auto.NXP正在寻求通过使其工具 ...

最新文章

  1. Hashmap链表长度为8时转换成红黑树,你知道为什么是8吗
  2. android 上下扫描动画,Android扫描雷达动画
  3. 关于centos docker版本过低导致 is not a valid repository/tag: invalid reference format
  4. Enterprise Library Policy Injection Application Block 之二: PIAB设计和实现原理
  5. vue .native 方法未定义_技术分享谈谈Vue的响应式原理
  6. Spring Boot菜鸟示例——Hello World
  7. 一些有用软件收藏(更新中)
  8. 查找下载外文文献,这个网站比知网好用多了,经过对比后,五星推荐给大家!
  9. 至强服务器性能排行,英特尔至强处理器排名天梯 至强cpu天梯2020排名
  10. 打开ps显示计算机内存不足怎么办,ps显示内存不足怎么办,教你ps显示内存不足怎么办...
  11. 大学计算机专业吐槽,大学专业吐槽集锦:分分钟让你感觉“前途无亮”!
  12. 移动医疗仍处于烧钱阶段,海量流量难变现
  13. ISO/IEC 9126软件质量标准
  14. centos 7 iso u盘安装_服务器系统CentOS安装教程
  15. 计算机中桌面位置更改,如何更改桌面文件路径 电脑桌面优化技巧
  16. PostgreSQL CAST 转换数据类型
  17. 【AI好书】不想被AI降维打击?美国“四院院士”写的这本深度学习科普书了解一下...
  18. 【Spark NLP】第 3 章:Apache Spark 上的 NLP
  19. java计算机毕业设计互联网保险网站源程序+mysql+系统+lw文档+远程调试
  20. BigDecimal使用过程中的问题记录

热门文章

  1. python之路径拼接urljoin
  2. 洛谷P4136 谁能赢呢?——博弈
  3. table导出Excel
  4. window7开放端sqlserver端口
  5. 产品问答 | 作为项目负责人,怎么提升成员工作斗志?
  6. 【pmcaff】其实一直有一个人在默默关注你
  7. 是是非非本寻常,我们要不要跳槽。
  8. 数据库-主键和外键及其约束
  9. 朋友圈玩分身术!逼死用户的节奏?
  10. 中兴通讯应用之星一键手机电子书解决方案