BloomFilter
定义:二进制向量数据结构,具有很好的空间和时间效率,用来检测一个元素是否为集合的一个成员,一般使用BloomFilter来去重;
BloomFilter是通过“位(bit)”来保存元素的,是一个初始值全为0的位数组;
添加元素:使用K个Hash函数得到元素的K个Hash值,以这K个Hash值作为数组的索引,把位数组中位于该索引的值设为1。
查找元素:与添加元素过程相似,使用K个Hash函数得到元素的K个Hash值,以这K个Hash值作为数组的索引,查找到索引位置的值,如有一个值为0,则代表该元素不存在于BloomFilter中;如果都为1,说明该元素存在于BloomFilter中,但有误判的概率。
举例:
位数组bloom:0000000000000000;
- 存入元素x:
元素x的三个Hash值为1、5和10,将x存入bloom中,bloom变为:0000010000100010; - 存入元素y:
元素y的三个Hash值为1、4和8,4和8所在的位为0,故y不存在于bloom中,将y存入bloom,bloom变为:0000010100110010; - 存入元素z:
元素z的三个Hash值为4、5和8,4、5和8所在的位为1,这时会判断为z已存在bloom中,为重复数据,但事实上z并不与x或y相同,故出现“误判”——将不是重复的数据判定为重复。
BloomFilter的优缺点:
- 牺牲正确率来节省时间和空间,效率更高;
- 往集合中插入的元素越多,错判“在集合内”的概率越大;
- 不能删除集合中的元素,删除某个元素可能会将其他元素的位值也发生改变;
相关值的设定
- 误判率f 的计算公式:
f=(1−(1−1m)kn)k,m为位数组大小,k为Hash函数个数,n为预计存入的最大数据量; f = ( 1 − ( 1 − 1 m ) k n ) k , m 为 位 数 组 大 小 , k 为 H a s h 函 数 个 数 , n 为 预 计 存 入 的 最 大 数 据 量 ;
当m 趋向于无穷时,误判率f 的计算公式可变为:
f=(1−(1−1m)kn)k=(1−(1−1m)−m−knm)k≈(1−enkm)k f = ( 1 − ( 1 − 1 m ) k n ) k = ( 1 − ( 1 − 1 m ) − m − k n m ) k ≈ ( 1 − e n k m ) k - 给定m 和n 值时,当 k=mnln2≈0.7mn k = m n l n 2 ≈ 0.7 m n 时f 的值为最小,为 (12)k≈0.6185mn ( 1 2 ) k ≈ 0.6185 m n ;
- 位数组的大小m:
m≥log2e∗nlog2(1f)
m
≥
l
o
g
2
e
∗
n
l
o
g
2
(
1
f
)
注:具体算法公示计算参考中,在此处的计算出错,
f=2−k⇒k=log21f⇒mnln2=log21f⇒m=log2e∗nlog2(1f) f = 2 − k ⇒ k = l o g 2 1 f ⇒ m n l n 2 = l o g 2 1 f ⇒ m = l o g 2 e ∗ n l o g 2 ( 1 f ) ,
(logaMn=nlogaM,logab∗logba=1) ( l o g a M n = n l o g a M , l o g a b ∗ l o g b a = 1 ) ;
如何获取更有用的BloomFilter?
- 选择合适的Hash函数,尽可能的返回范围更均匀的Hash值,减少误判率;
- 位数组的大小(m)非常重要,相对数据量,m太小的话,增加了误判的几率,m太大,又会浪费空间;
- Hash函数的个数(k)对索引值的均匀分配也很重要;
具体算法公式计算参考:
作者:Allen Sun
链接:https://www.cnblogs.com/allensun/archive/2011/02/16/1956532.html