目的:
过滤器使我们可以保留属于某个预定义值集合的记录。如果输出的结果有小的误判也不会是问题(只可能误判,绝不会漏判,失误率取决于hash算法),因为我们会在后续的操作中做进一步的检查。这里的预先确定的值列表称为热门值(hot values)集合。
对每条记录抽取其中一个特征。如果抽取的特征是布隆过滤器中所表示的值集合的成员,则保留这条记录;否则丢弃这条记录(或者做相反的处理)。
适用场景:
1.在过滤的过程中,数据可以被分成多条记录。
2.每条记录可以抽取一个特征,这个特征可以被一系列的热门值表示。
3.对于热门值有预先确定的元素集合。
4.能接受结果误判的存在。
已知应用:
1.移除大多数不受监视的值。
2.对成本很高的集合成员资格检查做数据的预先过滤。比如:使用布隆过滤的reduce端连接模式,可以减少传输到reduce的数据量,从而极大地减少网络的使用量。
3.hadoop中已经支持布隆过滤器:
org.apache.hadoop.util.bloom.BloomFilter;
个人理解:
布隆过滤器需要预先设置热门值:将值通过N个不同的seed计算出N个hash值,将这个N个值对应的位数组中的值设置为1。当判断一个值是否在热门值中时,先将这个值通过N个不同的seed计算出N个hash值,然后判断这个N个值对应的位数组中的值是否全为1。只有全为1时才判定该值在热门值中。
下面是一个简单的布隆过滤器实现:
package com.bloomFilter;
import java.util.BitSet;
/**
*
* @author xkey
*/
public class BloomFilter {
private static final int DEFAULT_SIZE = 2 << 24;//布隆过滤器的比特长度
private static final int[] seeds = {3,5,7, 11, 13, 31, 37, 61};//这里要选取质数,能很好的降低错误率
private static BitSet bits = new BitSet(DEFAULT_SIZE);
private static SimpleHash[] func = new SimpleHash[seeds.length];
public static void addValue(String value)
{
for(SimpleHash f : func)//将字符串value哈希为8个或多个整数,然后在这些整数的bit上变为1
bits.set(f.hash(value),true);
}
public static void add(String value)
{
if(value != null) addValue(value);
}
public static boolean contains(String value)
{
if(value == null) return false;
boolean ret = true;
for(SimpleHash f : func)//这里其实没必要全部跑完,只要一次ret==false那么就不包含这个字符串
ret = ret && bits.get(f.hash(value));
return ret;
}
public static void main(String[] args) {
String value = "xkeyideal@gmail.com";
for (int i = 0; i < seeds.length; i++) {
func[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);
}
add(value);
System.out.println(contains(value));
}
}
class SimpleHash {//这玩意相当于C++中的结构体
private int cap;
private int seed;
public SimpleHash(int cap, int seed) {
this.cap = cap;
this.seed = seed;
}
public int hash(String value) {//字符串哈希,选取好的哈希函数很重要
int result = 0;
int len = value.length();
for (int i = 0; i < len; i++) {
result = seed * result + value.charAt(i);
}
return (cap - 1) & result;
}
}
参考《hadoop设计模式》