布隆过滤器BloomFilter

BloomFilter原理图

x,y,zx,y,z经由哈希函数映射将各自在Bitmap中的3个位置置为1,当ww出现时,仅当3个标志位都为1时,才表示ww在集合中。图中所示的状况,布隆过滤器将断定w不在集合中。

算法比较复杂,也不是本文研究的范畴,直接使用已有的实现。java

google的guava包中提供了BloomFilter类,咱们直接使用它来进行一下简单的测试。 新建一个maven工程,引入guava包(建议你们使用这个包,里面有不少google封装好的代码);算法

<dependencies>  
    <dependency>  
        <groupId>com.google.guava</groupId>  
        <artifactId>guava</artifactId>  
        <version>22.0</version>  
    </dependency>  
</dependencies> 
复制代码

测试

  • 往过滤器里放一百万个数,而后去验证这一百万个数是否能经过过滤器,目的是校验是坏人是否必定被抓。
  • 另找1万个不在这一百万范围内的数,去验证漏网之鱼的几率,也就是布隆过滤器的误伤状况。
import com.google.common.hash.BloomFilter;  
import com.google.common.hash.Funnels;  
  
import java.util.ArrayList;  
import java.util.List;  

public class Test {  
    private static int size = 1000000;  
  
    private static BloomFilter<Integer> 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<Integer> list = new ArrayList<Integer>(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%呢。bash

跟踪源码

在create的多个重载方法中,最终走的是有4个参数的那个。咱们上面用的是有2个参数的,注意看图片最下面,咱们不填第三方参数时,默认补了一个0.03,这个就表明了容许的错误几率是3%。第四个参数是哈希算法,默认是BloomFilterStrategies.MURMUR128_MITZ_64。maven

在第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万分之一。google

private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.0001);  
复制代码

二次运行

咱们将28行改成10万个数,发现结果为“误伤12”。能够看到这个几率是比较靠谱的。 当几率为万分之一时,咱们看看空间占用。

此时bit容量已经从700多万到1900万了,函数数量也从5变成了13;几率从3%缩减到万分之一;

以上是布隆过滤器的简单使用。具体的应用场景,具体实现。spa

相关文章
相关标签/搜索