package com.xiaomi.oos.xmstore.oms.controller;
import java.util.BitSet;
public class Bloom {
private int times = 5; // 哈希次数
private int len = 100; // 空间长度
private long count = 64L; // 插入的元素个数
private double rate = 0.01; // 误报率
private BitSet bitSet;
public Bloom() {
this.init(10000, 0.01);
}
public void init(Long count, double rate) {
this.count = count;
this.rate = rate;
int len = -(int) ((Math.log(rate) * count) / (Math.pow(Math.log(2), 2)));
this.len = Math.max(len, 1);
int times = (int) (Math.log(2) * (this.len / this.count));
this.times = Math.max(times, 1);
this.bitSet = new BitSet(len);
}
public void init(int count, double rate) {
this.init(Long.valueOf(count), rate);
}
@Override
public String toString() {
return "元素个数:" + this.count + " 误报率:" + this.rate + " 过滤器长度:" + this.len + " 哈希次数:" + this.times;
}
public void add(Long id) {
long[] pos = this.pos(id);
for (long po : pos) {
this.bitSet.set(Math.toIntExact(po));
}
}
public void add(int id) {
this.add(Long.valueOf(id));
}
public boolean find(Long id) {
long[] pos = this.pos(id);
for (long po : pos) {
if (!this.bitSet.get(Math.toIntExact(po))) {
return false;
}
}
return true;
}
public boolean find(int id) {
return this.find(Long.valueOf(id));
}
public long[] pos(long id) {
long prev = id;
long[] pos = new long[this.times];
for (int i = 0; i < this.times; i++) {
int hashCode = Math.abs(String.valueOf(prev).hashCode());
int mod = hashCode % len;
prev = hashCode;
pos[i] = mod;
}
return pos;
}
public String dumpPos(long id) {
long[] pos = this.pos(id);
StringBuffer posS = new StringBuffer();
for (long po : pos) {
posS.append(po);
posS.append(" ");
}
return posS.toString();
}
public String dumpPos(int id) {
return this.dumpPos(Long.valueOf(id));
}
public static void main(String[] args) {
Bloom bloom = new Bloom();
bloom.init(100000, 0.01);
System.out.println(bloom);
System.out.println("10的hash分布: " + bloom.dumpPos(10));
StringBuffer added = new StringBuffer();
for (int i = 0; i < 10; i++) {
final int i1 = (int) (Math.random() * 10000);
bloom.add(i1);
added.append(i1);
added.append(" ");
}
System.out.println("插入10个0-10000的随机数: " + added.toString());
System.out.print("查找: ");
for (int i = 0; i < 10000; i++) {
if (bloom.find(i)) {
System.out.print(i + " ");
}
}
}
}
测试结果:
