日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Lucene工具箱之OpenBitSet(一)

發布時間:2025/3/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lucene工具箱之OpenBitSet(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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個數。

比如存儲46這兩個數,則byte中各個二進制位的狀態如下:

0


1


0


1


0


0


0


0


7


6


5


4


3


2


1


0


用二進制位的下標表示存儲的數,并在將二進制位的相應狀態設為1OpentBitSet正是利用上述原理來存儲數據。

3.4.2 OpenBitSet的簡單應用

假設有兩個集合A = {134105},B={5328}。計算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); //AB的并集

?????? 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);//AB的交集

?????? 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]之間的數,需要1long類型串聯起來。

如果存儲[0,127]之間的數,需要2long類型串聯起來。

如果存儲[0,191]之間的數,需要3long類型串聯起來。

……

如果存儲[0,(64N+m)] (N,m為非負整數,m<64)之間的數,需要Nlong類型串聯起來.

所以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]之間的數需要1long類型。

tits2words(256)=2;表示需要存儲[0,255]之間的數需要2long類型。

依此類推……

這樣傳參避免我們人工計算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)2index%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(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。