Bloom Filter就是这么一个空间利用率非常高的算法。我们先来看看这个算法的原理:
1 首先我们有一个长度为n的比特数组,开始的时候将这个比特数组里所有的元素都初始化为0
00000000000000000000
上面的比特数组n为20
2 然后选取k个哈希函数,这k个哈希函数产生的结果的值的范围在0到n-1之间(对于上面的比特数组,即0到19) 。对每个要添加进集合的对象进行哈希运算,然后将哈希计算结果作为数组的索引,将索引位置的比特位设置为1(不管该比特位原先为0还是为1)。
比如我们选取三个哈希函数,对于对象A哈希值为0,5,7。那么比特数组就为:
10000101000000000000
对象B的值为2,8,13,那么添加B后的比特数组为:
10100101100001000000
对象C为0,4,7(对象C的第一个哈希函数的值与对象A的相同了,没关系我们还是设置为1就可以了):
10101101100001000000
现在我们的Bloom Filter里已经有3个元素了。现在我们要判断某元素X是否在该集合中。就相当于我们要实现一个contains方法。那么这个方法如何实现呢?
对元素X采用相同的三个哈希函数哈希,然后以这三个哈希值为索引去比特数组里找。如果三个索引位置的比特位都为1我们就认为该元素在集合中,否则不是。
1 public class BloomFilter { 2 3 public static final byte [] bitvalues = new byte [] { 4 (byte)0x01, 5 (byte)0x02, 6 (byte)0x04, 7 (byte)0x08, 8 (byte)0x10, 9 (byte)0x20, 10 (byte)0x40, 11 (byte)0x80 12 }; 13 14 public void add (Key key) { 15 if(key == null){ 16 throw new NullPointerException("Key cannot be null"); 17 } 18 19 int [] h = hash.hash(key); 20 hash.clear(); 21 22 for (int i = 0;i<nbHash; i++){ 23 bits.set(h[i]); 24 } 25 26 public boolean membershipTest(Key key){ 27 if(key == null){ 28 throw new NullPointerException("key cannot be null"); 29 } 30 int [] h = hash.hash(key); 31 hash.clear(); 32 for(int i=0;i<nbHash;i++){ 33 if(!bit.get(h[i])){ 34 return false; 35 } 36 } 37 return true; 38 } 39 } 40 41 }