屬於轉貼java
1、 Bloom-Filter算法簡介。
Bloom-Filter,即布隆過濾器,1970年由Bloom中提出。它能夠用於檢索一個元素是否在一個集合中,其優勢是空間效率和查詢時間都遠遠超過其餘算法,其不足在於Bloom- Filter存在着誤判。
2、 Bloom-Filter的基本思想。
Bloom-Filter算法的核心思想就是利用多個不一樣的Hash函數來解決「衝突」。 計算某元素x是否在一個集合中,首先能想到的方法就是將全部的已知元素保存起來構成一個集合R,而後用元素x跟這些R中的元素一一比較來判斷是否存在於集合R中;咱們能夠採用鏈表等數據結構來實現。可是,隨着集合R中元素的增長,其佔用的內存將愈來愈大。試想,若是有幾千萬個不一樣網頁須要下載,所需的內存將足以佔用掉整個進程的內存地址空間。即便用MD5,UUID這些方法將URL轉成固定的短小的字符串,內存佔用也是至關巨大的.web
平常生活中,包括在設計計算機軟件時,咱們常常要判斷一個元素是否在一個集合中。好比在字處理軟件中,須要檢查一個英語單詞是否拼寫正確(也就是要判斷它是否在已知的字典中);在 FBI,一個嫌疑人的名字是否已經在嫌疑名單上;在網絡爬蟲裏,一個網址是否被訪問過等等。最直接的方法就是將集合中所有的元素存在計算機中,遇到一個新元素時,將它和集合中的元素直接比較便可。算法
通常來說,計算機中的集合是用哈希表(hash table)來存儲的。它的好處是快速準確,缺點是費存儲空間。當集合比較小時,這個問題不顯著,可是當集合巨大時,哈希表存儲效率低的問題就顯現出來了。
3、 Bloom-Filter的應用。
Bloom-Filter通常用於在大數據量的集合中斷定某元素是否存在。例如郵件服務器中的垃圾郵件過濾器。在搜索引擎領域,Bloom-Filter最經常使用於網絡蜘蛛(Spider)的URL過濾,網絡蜘蛛一般有一個 URL列表,保存着將要下載和已經下載的網頁的URL,網絡蜘蛛下載了一個網頁,從網頁中提取到新的URL後,須要判斷該URL是否已經存在於列表中。此時,Bloom-Filter算法是最好的選擇。
好比說,一個象 Yahoo,Hotmail 和 Gmai 那樣的公衆電子郵件(email)提供商,老是須要過濾來自發送垃圾郵件的人(spamer)的垃圾郵件。一個辦法就是記錄下那些發垃圾郵件的 email 地址。因爲那些發送者不停地在註冊新的地址,全世界少說也有幾十億個發垃圾郵件的地址,將他們都存起來則須要大量的網絡服務器。 服務器
布隆過濾器是由巴頓.布隆於一九七零年提出的。它其實是一個很長的二進制向量和一系列隨機映射函數。咱們經過上面的例子來講明起工做原理。網絡
假定咱們存儲一億個電子郵件地址,咱們先創建一個十六億二進制(比特),即兩億字節的向量,而後將這十六億個二進制位所有設置爲零。對於每個電子郵件地址 X,咱們用八個不一樣的隨機數產生器(F1,F2, ...,F8) 產生八個信息指紋(f1, f2, ..., f8)。再用一個隨機數產生器 G 把這八個信息指紋映射到 1 到十六億中的八個天然數 g1, g2, ...,g8。如今咱們把這八個位置的二進制位所有設置爲一。當咱們對這一億個 email 地址都進行這樣的處理後。一個針對這些 email 地址的布隆過濾器就建成了。(見下圖) 如今,讓咱們看看如何用布隆過濾器來檢測一個可疑的電子郵件地址 Y 是否在黑名單中。咱們用相同的八個隨機數產生器(F1, F2, ..., F8)對這個地址產生八個信息指紋 s1,s2,...,s8,而後將這八個指紋對應到布隆過濾器的八個二進制位,分別是 t1,t2,...,t8。若是 Y 在黑名單中,顯然,t1,t2,..,t8 對應的八個二進制必定是一。這樣在遇到任何在黑名單中的電子郵件地址,咱們都能準確地發現。
布隆過濾器決不會漏掉任何一個在黑名單中的可疑地址。可是,它有一條不足之處。也就是它有極小的可能將一個不在黑名單中的電子郵件地址斷定爲在黑名單中,由於有可能某個好的郵件地址正巧對應八個都被設置成一的二進制位。好在這種可能性很小。咱們把它稱爲誤識機率。在上面的例子中,誤識機率在萬分之一如下。
布隆過濾器的好處在於快速,省空間。可是有必定的誤識別率。常見的補救辦法是在創建一個小的白名單,存儲那些可能別誤判的郵件地址。數據結構
1. 使用Java 自帶的dom
private BitSet bits = new BitSet(defaultSize);ide
import java.util.BitSet;
public class bloomFilter {
private int defaultSize = 5000 << 10000;
private int basic = defaultSize -1;
private String key = null;
private BitSet bits = new BitSet(defaultSize);
public bloomFilter(String key){
this.key = key;
}
private int[] lrandom(){
int[] randomsum = new int[8];
int random1 = hashCode(key,1);
int random2 = hashCode(key,2);
int random3 = hashCode(key,3);
int random4 = hashCode(key,4);
int random5 = hashCode(key,5);
int random6 = hashCode(key,6);
int random7 = hashCode(key,7);
int random8 = hashCode(key,8);
randomsum[0] = random1;
randomsum[1] = random2;
randomsum[2] = random3;
randomsum[3] = random4;
randomsum[4] = random5;
randomsum[5] = random6;
randomsum[6] = random7;
randomsum[7] = random8;
return randomsum;
}
private int[] sameLrandom(){
int[] randomsum = new int[8];
int random1 = hashCode(key,1);
int random2 = hashCode(key,1);
int random3 = hashCode(key,1);
int random4 = hashCode(key,1);
int random5 = hashCode(key,1);
int random6 = hashCode(key,1);
int random7 = hashCode(key,1);
int random8 = hashCode(key,1);
randomsum[0] = random1;
randomsum[1] = random2;
randomsum[2] = random3;
randomsum[3] = random4;
randomsum[4] = random5;
randomsum[5] = random6;
randomsum[6] = random7;
randomsum[7] = random8;
return randomsum;
}
private void add(){
if(exist()){
System.out.println("已經包含("+key+")");
return;
}
int keyCode[] = lrandom();
bits.set(keyCode[0]);
bits.set(keyCode[1]);
bits.set(keyCode[2]);
bits.set(keyCode[3]);
bits.set(keyCode[4]);
bits.set(keyCode[5]);
bits.set(keyCode[6]);
bits.set(keyCode[7]);
}
private boolean exist(){
int keyCode[] = lrandom();
if(bits.get(keyCode[0])&&
bits.get(keyCode[1])
&&bits.get(keyCode[2])
&&bits.get(keyCode[3])
&&bits.get(keyCode[4])
&&bits.get(keyCode[5])
&&bits.get(keyCode[6])
&&bits.get(keyCode[7])){
return true;
}
return false;
}
private boolean set0(){
if(exist()){
int keyCode[] = lrandom();
bits.clear(keyCode[0]);
bits.clear(keyCode[1]);
bits.clear(keyCode[2]);
bits.clear(keyCode[3]);
bits.clear(keyCode[4]);
bits.clear(keyCode[5]);
bits.clear(keyCode[6]);
bits.clear(keyCode[7]);
return true;
}
return false;
}
private int hashCode(String key,int Q){
int h = 0;
int off = 0;
char val[] = key.toCharArray();
int len = key.length();
for (int i = 0; i < len; i++) {
h = (30 + Q) * h + val[off++];
}
return changeInteger(h);
}
private int changeInteger(int h) {
return basic & h;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
bloomFilter f = new bloomFilter("http://www.agrilink.cn/");
System.out.println(f.defaultSize);
f.add();
System.out.println(f.exist());
f.set0();
System.out.println(f.exist());
}
}
2. 還有一個java 版的 ,也是 使用 bitset函數
import java.util.BitSet;
public class SimpleBloomFilter {
private static final int DEFAULT_SIZE =2 << 24 ;
private static final int [] seeds =new int []{5,7, 11 , 13 , 31 , 37 , 61};
private BitSet bits= new BitSet(DEFAULT_SIZE);
private SimpleHash[] func=new SimpleHash[seeds.length];
public SimpleBloomFilter() {
for( int i= 0 ; i< seeds.length; i ++ ) {
func[i]=new SimpleHash(DEFAULT_SIZE, seeds[i]);
}
}
public void add(String value) {
for(SimpleHash f : func) {
bits.set(f.hash(value), true );
}
}
public boolean contains(String value) {
if(value ==null ) {
return false ;
}
boolean ret = true ;
for(SimpleHash f : func) {
ret=ret&& bits.get(f.hash(value));
}
return ret;
}
//內部類,simpleHash
public static class SimpleHash {
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;
}
}
public static void main(String[] args) {
String value = "stone2083@yahoo.cn" ;
SimpleBloomFilter filter=new SimpleBloomFilter(); System.out.println(filter.contains(value)); filter.add(value); System.out.println(filter.contains(value)); } }其它資料http://blog.csdn.net/hguisu/article/details/7866173