开发场景: 制作主播排行榜单(白名单),大概10W + 的主播,但是白名单只有1W +,已经存在与表,拉取插入bloomfilter,项目初始化即可存入bloomfilter,每次制作榜单需要的数据即可过滤主播 手动实现BloomFilter代码:
/**
* @description: 手动实现bloomFilter,可能存在,一定不存在
* @author: Ding Yawu
* @create: 2022/2/1 14:21
*/
public class MyBloomFilter {
// 位数组的大小
private static final int DEFAULT_SIZE = 2 << 24;
// hash函数的种子
private static final int[] SEEDS = new int[]{3, 13, 46};
// 位数组,数组中的元素只能是 0 或者 1
private BitSet bits = new BitSet(DEFAULT_SIZE);
// hash函数
private ExtHash[] func = new ExtHash[SEEDS.length];
public MyBloomFilter() {
for (int i = 0; i < SEEDS.length; i++) {
func[i] = new ExtHash(DEFAULT_SIZE, SEEDS[i]);
}
}
// 添加元素到位数组
public void add(Object value) {
for (ExtHash f : func) {
bits.set(f.hash(value), true);
}
}
// 判断指定元素是否存在于位数组
public boolean contains(Object value) {
boolean ret = true;
for (ExtHash f : func) {
ret = ret && bits.get(f.hash(value));
// hash函数有一个计算出为false,则直接返回
if (!ret) {
return ret;
}
}
return ret;
}
// hash函数类
public static class ExtHash {
private int cap;
private int seed;
public ExtHash(int cap, int seed) {
this.cap = cap;
this.seed = seed;
}
public int hash(Object value) {
int h;
return (value == null) ? 0 : Math.abs(seed * (cap - 1) & ((h = value.hashCode()) ^ (h >>> 16)));
}
}
public static void main(String[] args) {
Integer value1 = 13423;
Integer value2 = 22131;
MyBloomFilter filter = new MyBloomFilter();
// false
System.out.println(filter.contains(value1));
// false
System.out.println(filter.contains(value2));
filter.add(value1);
filter.add(value2);
// true
System.out.println(filter.contains(value1));
// true
System.out.println(filter.contains(value2));
}
}
我对BloomFilter的理解就是可能存在,但一定不存在尤其适合做榜单数据的时候要求不是那么精确,即使像邮件那样错判了也是可以接受的。
测试guava包的BloomFilter
/**
* @description:
* @author: Ding Yawu
* @create: 2022/2/1 14:36
*/
public class GuavaFilter {
public static void main(String[] args) {
// 创建布隆过滤器对象,最多元素数量为50000,期望误报概率为0.01
BloomFilter<Integer> filter = BloomFilter.create(Funnels.integerFunnel(), 50000, 0.01);
// 判断指定元素是否存在
// false
System.out.println(filter.mightContain(1));
// false
System.out.println(filter.mightContain(2));
// 将元素添加进布隆过滤器
filter.put(1);
filter.put(2);
// true
System.out.println(filter.mightContain(1));
// true
System.out.println(filter.mightContain(2));
}
}
guava包中轮子已经造好了,拿来直接使用就好了,在实践中也可以直接采用redis的bloom插件。