目录
一、什么是布隆过滤器
布隆过滤器实际上是一个很长的二进制向量和一系列的随机映射函数。函数的作用是计算元素的hash值,并把计算后元素的下标映射到数组中。
布隆过滤器提供两个参数,预计加入的元素大小n和运行错误率f,布隆过滤器中有算法根据这两个参数计算出二进制数组的大小l和hash函数的个数k。f越低,l越大,空间占用越大。f越低,k越多,计算时间越长。
往布隆过滤器中增加元素,添加的key根据k个函数得到多个hash值,hash值对数组长度取模得到数组下标对应位置,然后将对应位置置为1。查询时同样把元素以同样的方式得到下标,当下标位置全部为1则存在(存在误判可能性),当有一个下标位置为0则不存在。
二、布隆过滤器的优缺点
优点:时间复杂度低,O(n),存储空间小
缺点:有一定的误判率,但是可以通过调整参数来降低误判率
三、布隆过滤器的使用场景
布隆过滤器可以判断一定不存在,或者可能存在。
例如:解决Redis缓存穿透问题,邮件的黑名单过滤,爬虫网址的过滤等。
四、布隆过滤器的使用
1、使用google的Guava提供的布隆过滤器
引入依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
public static void main(String[] args) {
//预计加入的元素大小
int n=100000;
//误判率
double f=0.0001;
BloomFilter<Integer> bloomFilter =
BloomFilter.create(Funnels.integerFunnel(),n,f);
for (int m=0;m<n;m++){
bloomFilter.put(m);
}
int count=0;
for(int i=n;i<n+200000;i++){
if(bloomFilter.mightContain(i)){
count++;
}
}
System.out.println("误判率"+count/n);
}
2、Redisson实现布隆过滤器
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.0</version>
</dependency>
public static void main(String[] args) {
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379");
RedissonClient redisson = Redisson.create(config);
RBloomFilter<Integer> bloomFilter = redisson.getBloomFilter("bloom-filter");
//初始化布隆过滤器:设置预计加入的元素大小和误差率
bloomFilter.tryInit(100000L, 0.03);
for(int i=0;i<100000;i++){
bloomFilter.add(i);
}
int count=0;
for(int i=100000+1;i<100000*2;i++){
if(bloomFilter.contains(i)){
count++;
}
}
System.out.println("误判次数:"+count);
}