Bloom Filter
1.介绍
Bloom Filter,被译作称布隆过滤器,是一种数据结构,Bloom Filter包含一个位数组和k个映射函数,一般提供两个方法。contains 方法用来判断一个元素是否存在于位数组中,addValue方法用来将元素映射入位数组
2.使用场景
2.1黑名单
对用户的IP或者Email进行过滤,如果IP或者Email被判断存在于位数组中,则禁止通过
2.2URL去重
判断URL是否已经被抓取
2.3字典纠错
判断单词是否正确
3.原理
设存在一组元素(x1,x2,x3.....,xm),K个函数,f1,f2,...fk,一个n位的数组A。对于元素xi可以存在如下操作:
函数addValue(xi):
--f1(xi)通过hash运算将xi映射成一个整数t1,然后将A[t1]值设置为1
--f2(xi)通过hash运算将xi映射成一个整数t2,然后将A[t2]值设置为1
.............
--fk(xi)通过hash运算将xi映射成一个整数tk,然后将A[tk]值设置为1
函数contains(xi):
--f1(xi)通过hash运算将xi映射为一个整数t1,判断A[t1]的值是否为1,如果为1,将r1值设为true,否则设为false
............
--fk(xi)通过hash运算将xi映射为一个整数tk,判断A[tk]的值是否为1,如果为1,将rk的值设为true,否则设为false
--使result=r1&&r2&&....&&rk
--返回result
注意:Bloom Filter不会存在重复的情况,但是可能存在遗漏的情况,对于元素xi并不存在于位数组中,但是contains(xi)返回true,判断结果为已经存在于位数组中。
错误率计算:
设位数组在将所有元素(x1,x2,x3,....,xn)加入位数组A后,第q位不为1的概率位
q' 为位数组为1的概率,则q' 的期望为
则错误率为
4.实现
package utils;
import java.util.BitSet;
import service.UrlService;
/**
* bloomfilter
* @author ym
*
*/
public class BloomFilter {
// default storage size
public static int default_size=1<<25;
//hash seed
public static int[] seed={3,23,11,5,9,15,8,20};
//function array to hash url
public BloomHash[] BH;
//storage url hash value
public BitSet bitSet=null;
public BloomFilter(){
bitSet=new BitSet(default_size);
BH =new BloomHash[seed.length];
for(int i=0;i
BH[i]=new BloomHash(default_size,seed[i]);
}
}
/**
* add url to bloom
* @param url
*/
public void addValue(String value){
for(BloomHash fun:BH){
bitSet.set(fun.bloomhash(value),true);
}
}
/**
* judge url is or not exit in bloom
* @param url
* @return
*/
public boolean contains(String value){
boolean ret = true;
for(BloomHash func:BH){
ret=ret&&bitSet.get(func.bloomhash(value));
}
return ret;
}
/**
* fill BloomFilter
*/
public void fill(){
UrlService urlService = new UrlService();
UrlQueue queue = urlService.getVisitedURLQueue();
while(!queue.isEmpty()){
this.addValue(queue.poll());
}
}
/**
* a hash class
* @author
*
*/
public class BloomHash{
int size=0;
int ret=0;
public BloomHash(int size,int ret){
this.size=size;
this.ret=ret;
}
/**
* hash url to int
* @param url
* @return
*/
public int bloomhash(String value){
int result=0;
int len=value.length();
for(int i=0;i
result=result*ret+value.charAt(i);
}
return (size-1)&result;
}
}
}