前言
Bloom過濾器,通過將字符串映射為信息指紋從而節省了空間。Bloom過濾器的原理為,將一個字符串通過一定算法映射為八個Hash值,將八個Hash值對應位置的Bitset位進行填充。在進行校驗的時候,通過同樣的算法計算八個Hash值,八個Hash值全部存在才可以認定為該字符串在集合中存在。
四個Hash值的布隆過濾器:
通過這樣的一個算法,可以無需將字符串的MD5值存儲在內存中,只需要定義一定長度的Bitset即可,從而大大節約了空間。
應用場景
Bloom過濾器可以廣泛應用於判斷集合中是否存在某個元素的大量數據場景,比如黑名單、爬蟲訪問記錄。
實現
關於布隆過濾器的實現,代碼如下:
import java.util.BitSet;
/*
簡單的Bloom過濾器實現
*/
public class BloomDemo {
private static final int SIZE = 1<<24;
BitSet bitSet=new BitSet(SIZE);
Hash[] hashs=new Hash[8];
private static final int seeds[]=new int[]{3,5,7,9,11,13,17,19};
public static void main(String[] args) {
String email="zhenlingcn@126.com";
BloomDemo bloomDemo=new BloomDemo();
System.out.println(email+"是否在列表中: "+bloomDemo.contains(email));
bloomDemo.add(email);
System.out.println(email+"是否在列表中: "+bloomDemo.contains(email));
email="zhenlingcn@163.com";
System.out.println(email+"是否在列表中: "+bloomDemo.contains(email));
}
public BloomDemo(){
for (int i = 0; i < seeds.length; i++) {
hashs[i]=new Hash(seeds[i]);
}
}
public void add(String string){
for(Hash hash:hashs){
bitSet.set(hash.getHash(string),true);
}
}
public boolean contains(String string){
boolean have=true;
for(Hash hash:hashs){
have&=bitSet.get(hash.getHash(string));
}
return have;
}
class Hash{
private int seed = 0;
public Hash(int seed){
this.seed=seed;
}
public int getHash(String string){
int val=0;
int len=string.length();
for (int i = 0; i < len; i++) {
val=val*seed+string.charAt(i);
}
return val&(SIZE-1);
}
}
}
上面的Hash算法采用了最簡單的基於seed和ascii碼的Hash算法。八個種子均采用質數,減少HASH碰撞的概率。