参考博客:https://blog.csdn.net/xinzhongtianxia/article/details/81294922
布隆过滤器
百度百科:
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
如果想要判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢(O(n),O(logn))。不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。这就是布隆过滤器的基本思想。
Hash面临的问题就是冲突。假设Hash函数是良好的,如果我们的位阵列长度为m个点,那么如果我们想将冲突率降低到例如 1%, 这个散列表就只能容纳m / 100个元素。显然这就不叫空间效率了(Space-efficient)了。解决方法也简单,就是使用多个Hash,如果它们有一个说元素不在集合中,那肯定就不在。如果它们都说在,虽然也有一定可能性它们在说谎,不过直觉上判断这种事情的概率是比较低的。
应用
网页URL的去重,垃圾邮件的判别,集合重复元素的判别,查询加速(比如基于key-value的存储系统)等。
个人理解
如果有一亿个64位长度的url需要加入到内存,请使用占用空间最少的办法。
建立一个 m个bit 长的(1byte =8 bits)数组 ,准备k个hash函数,每个url 通过h1、h2。。。hk 个hash函数进行运算,得到的数字%m ,并将bits数组中对应位置进行取反(初始为0,取反为1),下次查询时,再进行同样的操作,如果每个函数的hash值最后的值在数组上的状态都是1,那就说明这个url已经加入到内存中了。
m的取值与需要处理的样本数量、预期失误率有关
n为样本量、p为失误率(比如万分之一、百万分之一)
哈希函数的个数 k 向上取整:
真实失误率估算:
空间要求非常严重、单样本空间大 使用布隆过滤器
面试提示点:
黑名单问题、要求问题极为苛刻、单样本空间大、允不允许失误率。
下面的应用来源自:https://blog.csdn.net/xinzhongtianxia/article/details/81294922,感谢这位博主的讲解
BloomFilter的应用
黑名单
比如邮件黑名单过滤器,判断邮件地址是否在黑名单中
排序(仅限于BitSet)
仔细想想,其实BitSet在set(int value)的时候,“顺便”把value也给排序了。
网络爬虫
判断某个URL是否已经被爬取过
K-V系统快速判断某个key是否存在
典型的例子有Hbase,Hbase的每个Region中都包含一个BloomFilter,用于在查询时快速判断某个key在该region中是否存在,如果不存在,直接返回,节省掉后续的查询。