You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
5.0 KiB
182 lines
5.0 KiB
package com.fr.third.bitmap.roaringbitmap; |
|
|
|
import java.util.Iterator; |
|
|
|
/** |
|
* Created by loy on 2021/7/13. |
|
* |
|
* <p>兼容新引擎插件中用到的这个类,后续会删除 |
|
*/ |
|
@Deprecated |
|
public class RoaringBitmap { |
|
|
|
private byte[] value = new byte[1024]; |
|
private int length; |
|
|
|
public void add(int n) { |
|
checkIndex(n); |
|
ensureCap(n); |
|
int idx0 = n / 8; |
|
int idx1 = n % 8; |
|
if ((value[idx0] & (1 << idx1)) == 0) { |
|
length++; |
|
value[idx0] |= (1 << idx1); |
|
} |
|
} |
|
|
|
public void remove(int n) { |
|
checkIndex(n); |
|
if (n >= value.length * 8) { |
|
return; |
|
} |
|
int idx0 = n / 8; |
|
int idx1 = n % 8; |
|
if ((value[idx0] & (1 << idx1)) != 0) { |
|
length--; |
|
value[idx0] &= ~(1 << idx1); |
|
} |
|
} |
|
|
|
public boolean contains(int n) { |
|
checkIndex(n); |
|
if (n >= value.length * 8) { |
|
return false; |
|
} |
|
int idx0 = n / 8; |
|
int idx1 = n % 8; |
|
return (value[idx0] & (1 << idx1)) != 0; |
|
} |
|
|
|
public void flip(long rangeStart, long rangeEnd) { |
|
int sIdx0 = (int) ((rangeStart + 7) / 8); |
|
int sIdx1 = (int) (rangeStart % 8); |
|
int eIdx0 = (int) (rangeEnd / 8); |
|
int eIdx1 = (int) (rangeEnd % 8); |
|
int lenDiff = 0; |
|
if (sIdx1 > 0) { |
|
byte b = value[sIdx0 - 1]; |
|
byte b2 = (byte) (~(b & 0xff) >> sIdx1 << sIdx1 + ((b & 0xff) << (32 - sIdx1) >> (32 - sIdx1))); |
|
value[sIdx0 - 1] = b2; |
|
lenDiff += countInByte(b2) - countInByte(b); |
|
} |
|
for (int i = sIdx0; i < eIdx0; i++) { |
|
value[i] = (byte) ~(value[i]); |
|
lenDiff += countInByte(value[i]) * 2 - 8; |
|
} |
|
if (eIdx1 > 0) { |
|
byte b = value[eIdx0]; |
|
byte b2 = (byte) (((b & 0xff) >> eIdx1 << eIdx1) + ~(b & 0xff) << (32 - eIdx1) >> (32 - eIdx1)); |
|
value[eIdx0] = b2; |
|
lenDiff += countInByte(b2) - countInByte(b); |
|
} |
|
length += lenDiff; |
|
} |
|
|
|
public int getCardinality() { |
|
return length; |
|
} |
|
|
|
@Override |
|
public RoaringBitmap clone() { |
|
RoaringBitmap bm = new RoaringBitmap(); |
|
bm.length = length; |
|
bm.value = new byte[value.length]; |
|
System.arraycopy(value, 0, bm.value, 0, value.length); |
|
return bm; |
|
} |
|
|
|
public static RoaringBitmap and(RoaringBitmap bm1, RoaringBitmap bm2) { |
|
int len = Integer.min(bm1.length, bm2.length); |
|
RoaringBitmap bm = new RoaringBitmap(); |
|
bm.value = new byte[len]; |
|
for (int i = 0; i < len; i++) { |
|
byte b = (byte) (bm1.value[i] & bm2.value[i]); |
|
if (b == 0) { |
|
continue; |
|
} |
|
bm.length += countInByte(b); |
|
} |
|
return bm; |
|
} |
|
|
|
public static int andCardinality(RoaringBitmap bm1, RoaringBitmap bm2) { |
|
int len = Integer.min(bm1.length, bm2.length); |
|
int count = 0; |
|
for (int i = 0; i < len; i++) { |
|
byte b = (byte) (bm1.value[i] & bm2.value[i]); |
|
if (b == 0) { |
|
continue; |
|
} |
|
count++; |
|
} |
|
return count; |
|
} |
|
|
|
public Iterator<Integer> iterator() { |
|
return new Iterator<Integer>() { |
|
private int idx0 = 0; |
|
private int idx1 = 0; |
|
@Override |
|
public boolean hasNext() { |
|
while (idx0 < value.length) { |
|
if (value[idx0] != 0) { |
|
byte b = value[idx0]; |
|
while (idx1 < 8) { |
|
if ((b & (1 << idx1)) != 0) { |
|
return true; |
|
} |
|
idx1++; |
|
} |
|
} |
|
idx0++; |
|
idx1 = 0; |
|
} |
|
return false; |
|
} |
|
|
|
@Override |
|
public Integer next() { |
|
if (hasNext()) { |
|
int v = idx0 * 8 + idx1; |
|
idx1++; |
|
if (idx1 >= 8) { |
|
idx1 = 0; |
|
idx0++; |
|
} |
|
return v; |
|
} |
|
return null; |
|
} |
|
}; |
|
} |
|
|
|
private void ensureCap(int n) { |
|
int idx = (n + 7) / 8; |
|
int len = value.length; |
|
while (len < idx) { |
|
len <<= 1; |
|
} |
|
if (len > value.length) { |
|
byte[] value2 = new byte[len]; |
|
System.arraycopy(value, 0, value2, 0, value.length); |
|
value = value2; |
|
} |
|
} |
|
|
|
private void checkIndex(int n) { |
|
if (n < 0) { |
|
throw new ArrayIndexOutOfBoundsException(); |
|
} |
|
} |
|
|
|
private static int countInByte(byte b) { |
|
int count = 0; |
|
while (b != 0) { |
|
if ((b & 0x01) == 0x01) { |
|
count++; |
|
} |
|
b = (byte) ((b & 0xff) >> 1); |
|
} |
|
return count; |
|
} |
|
}
|
|
|