从上一篇可以得知,BloomFilter的关键在于hash算法的设定和bit数组的大小确定,通过权衡得到一个错误概率可以接受的结果。
算法比较复杂,也不是我们研究的范畴,我们直接使用已有的实现。
google的guava包中提供了BloomFilter类,我们直接使用它来进行一下简单的测试。
新建一个maven工程,引入guava包
com.google.guava
guava
22.0
一 我们往过滤器里放一百万个数,然后去验证这一百万个数是否能通过过滤器,目的是校验是坏人是否一定被抓。
二 我们另找1万个不在这一百万范围内的数,去验证漏网之鱼的概率,也就是布隆过滤器的误伤情况。
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import java.util.ArrayList;
import java.util.List;
/**
* Created by admin on 17/7/7.
* 布隆过滤器
*/
public class Test {
private static int size = 1000000;
private static BloomFilter bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size);
public static void main(String[] args) {
for (int i = 0; i < size; i++) {
bloomFilter.put(i);
}
for (int i = 0; i < size; i++) {
if (!bloomFilter.mightContain(i)) {
System.out.println("有坏人逃脱了");
}
}
List list = new ArrayList(1000);
for (int i = size + 10000; i < size + 20000; i++) {
if (bloomFilter.mightContain(i)) {
list.add(i);
}
}
System.out.println("有误伤的数量:" + list.size());
}
}
误伤的数量是330.也就是有330个不在过滤器内的值,被认为在过滤器里,被误伤了。
错误概率是3%作用,为毛是3%呢。我们跟踪源码看一下就知道了。
在create的多个重载方法中,最终走的是有4个参数的那个。我们上面用的是有2个参数的,注意看图片最下面,我们不填第三方参数时,默认补了一个0.03,这个就代表了允许的错误概率是3%。第四个参数是哈希算法,默认是BloomFilterStrategies.MURMUR128_MITZ_64,这个我们不去管它,反正也不懂。
在第127行可以看到,要存下这一百万个数,位数组的大小是7298440,700多万位,实际上要完整存下100万个数,一个int是4字节32位,我们需要4X8X1000000=3千2百万位,差不多只用了1/5的容量,如果是HashMap,按HashMap 50%的存储效率,我们需要6千4百万位,所有布隆过滤器占用空间很小,只有HashMap的1/10-1/5作用。
128行是hash函数的数量,是5,也就是说系统觉得要保证3%的错误率,需要5个函数外加700多万位即可。用3%误差换十分之一的内存占用。
我们也可以修改这个错误概率,譬如我们改为0.0001万分之一。
private static BloomFilter bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.0001);
再次运行看看
我们将28行改为10万个数,发现结果为“误伤12”。可以看到这个概率是比较靠谱的。
当概率为万分之一时,我们看看空间占用。
此时bit容量已经从700多万到1900万了,函数数量也从5变成了13.概率从3%缩减到万分之一。
这就是布隆过滤器的简单使用。具体的应用场景,具体实现。