redis 布隆过滤器
******************
相关jar包
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
******************
相关类及接口
BloomFilter:布隆过滤器类
public final class BloomFilter<T> implements Predicate<T>, Serializable {
private final LockFreeBitArray bits; //位数组
private final int numHashFunctions; //hash函数的个数
private final Funnel<? super T> funnel; //将任意对象转换为PrimitiveSink类型
private final BloomFilter.Strategy strategy; //位数组具体添加、判断策略
private BloomFilter(LockFreeBitArray bits, int numHashFunctions, Funnel<? super T> funnel, BloomFilter.Strategy strategy) {
//仅有一个私有构造方法
***************
创建BloomFilter
public static <T> BloomFilter<T> create(Funnel<? super T> funnel, int expectedInsertions, double fpp) {
public static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions, double fpp) {
static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions, double fpp, BloomFilter.Strategy strategy) {
public static <T> BloomFilter<T> create(Funnel<? super T> funnel, int expectedInsertions) {
public static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions) {
***************
常用方法
public boolean mightContain(T object) {
return this.strategy.mightContain(object, this.funnel, this.numHashFunctions, this.bits);
}//判断对象是否存在
public boolean put(T object) {
return this.strategy.put(object, this.funnel, this.numHashFunctions, this.bits);
}//将对象添加进布隆过滤器
public long approximateElementCount() {
long bitSize = this.bits.bitSize();
long bitCount = this.bits.bitCount();
double fractionOfBitsSet = (double)bitCount / (double)bitSize;
return DoubleMath.roundToLong(-Math.log1p(-fractionOfBitsSet) * (double)bitSize / (double)this.numHashFunctions, RoundingMode.HALF_UP);
}//粗略估计元素的个数
。。。。
}
strategy:该类为BloomFilter的内部类,进行对象添加、判断
interface Strategy extends Serializable {
<T> boolean put(T var1, Funnel<? super T> var2, int var3, LockFreeBitArray var4);
//向布隆过滤器添加对象
<T> boolean mightContain(T var1, Funnel<? super T> var2, int var3, LockFreeBitArray var4);
//判断对象是否存在
int ordinal();
}
BloomFilterStrategies:startegy的枚举实现类
enum BloomFilterStrategies implements Strategy {
MURMUR128_MITZ_32 {
public <T> boolean put(T object, Funnel<? super T> funnel, int numHashFunctions, BloomFilterStrategies.LockFreeBitArray bits) {
long bitSize = bits.bitSize();
long hash64 = Hashing.murmur3_128().hashObject(object, funnel).asLong();
//使用HashFunction将object最终转换为HashCode,再通过asLong转换为长整形
int hash1 = (int)hash64;
int hash2 = (int)(hash64 >>> 32);
boolean bitsChanged = false;
for(int i = 1; i <= numHashFunctions; ++i) {
int combinedHash = hash1 + i * hash2;
if (combinedHash < 0) {
combinedHash = ~combinedHash;
}
bitsChanged |= bits.set((long)combinedHash % bitSize);
}
return bitsChanged;
}//向布隆过滤器添加对象
public <T> boolean mightContain(T object, Funnel<? super T> funnel, int numHashFunctions, BloomFilterStrategies.LockFreeBitArray bits) {
。。。。
}//判断对象是否存在
MURMUR128_MITZ_64 {
//如果不指定,默认使用该策略
public <T> boolean put(T object, Funnel<? super T> funnel, int numHashFunctions, BloomFilterStrategies.LockFreeBitArray bits) {
long bitSize = bits.bitSize();
byte[] bytes = Hashing.murmur3_128().hashObject(object, funnel).getBytesInternal();
//使用HashFunction将Object转换为HashCode,在调用getBytesInternal()方法获得字节数组
long hash1 = this.lowerEight(bytes);
long hash2 = this.upperEight(bytes);
boolean bitsChanged = false;
long combinedHash = hash1;
for(int i = 0; i < numHashFunctions; ++i) {
bitsChanged |= bits.set((combinedHash & 9223372036854775807L) % bitSize);
combinedHash += hash2;
}
return bitsChanged;
}//向布隆过滤器添加对象
public <T> boolean mightContain(T object, Funnel<? super T> funnel, int numHashFunctions, BloomFilterStrategies.LockFreeBitArray bits) {
。。。。
}//判断对象是否存在
}
HashFunction:获取HashCode对象
public interface HashFunction {
Hasher newHasher();
Hasher newHasher(int var1);
HashCode hashBytes(byte[] var1);
HashCode hashBytes(byte[] var1, int var2, int var3);
HashCode hashBytes(ByteBuffer var1);
HashCode hashInt(int var1);
HashCode hashLong(long var1);
HashCode hashUnencodedChars(CharSequence var1);
HashCode hashString(CharSequence var1, Charset var2);
<T> HashCode hashObject(T var1, Funnel<? super T> var2);
int bits();
}
HashCode类:获得long、int、byte[]等数据
public abstract class HashCode {
private static final char[] hexDigits = "0123456789abcdef".toCharArray();
HashCode() {
}
public abstract int bits();
public abstract int asInt();
public abstract long asLong();
public abstract long padToLong();
public abstract byte[] asBytes();
byte[] getBytesInternal() {
return this.asBytes();
}
。。。。
}
Funnel接口:将对象T转换为PrimitiveSink类型
public interface Funnel<T> extends Serializable {
void funnel(T var1, PrimitiveSink var2);
}
Funnels:返回实现funnel接口的对象实例
public final class Funnels {
private Funnels() {
}
public static Funnel<byte[]> byteArrayFunnel() {
return Funnels.ByteArrayFunnel.INSTANCE;
}
public static Funnel<CharSequence> unencodedCharsFunnel() {
return Funnels.UnencodedCharsFunnel.INSTANCE;
}
public static Funnel<CharSequence> stringFunnel(Charset charset) {
return new Funnels.StringCharsetFunnel(charset);
}
public static Funnel<Integer> integerFunnel() {
return Funnels.IntegerFunnel.INSTANCE;
}
public static <E> Funnel<Iterable<? extends E>> sequentialFunnel(Funnel<E> elementFunnel) {
return new Funnels.SequentialFunnel(elementFunnel);
}
public static Funnel<Long> longFunnel() {
return Funnels.LongFunnel.INSTANCE;
}
public static OutputStream asOutputStream(PrimitiveSink sink) {
return new Funnels.SinkAsStream(sink);
}
private static enum LongFunnel implements Funnel<Long> {
INSTANCE;
private LongFunnel() {
}
public void funnel(Long from, PrimitiveSink into) {
into.putLong(from);
}
public String toString() {
return "Funnels.longFunnel()";
}
}
。。。。
}
PrimitiveSink接口:将相关数据转换为PrimitiveSink类型数据
public interface PrimitiveSink {
PrimitiveSink putByte(byte var1);
PrimitiveSink putBytes(byte[] var1);
PrimitiveSink putBytes(byte[] var1, int var2, int var3);
PrimitiveSink putBytes(ByteBuffer var1);
PrimitiveSink putShort(short var1);
PrimitiveSink putInt(int var1);
PrimitiveSink putLong(long var1);
PrimitiveSink putFloat(float var1);
PrimitiveSink putDouble(double var1);
PrimitiveSink putBoolean(boolean var1);
PrimitiveSink putChar(char var1);
PrimitiveSink putUnencodedChars(CharSequence var1);
PrimitiveSink putString(CharSequence var1, Charset var2);
}