bloom filter 的Java 版
http://www.cnblogs.com/hitwtx/archive/2011/08/24/2152180.html
一、 Bloom-Filter算法簡介。
?????? Bloom-Filter,即布隆過濾器,1970年由Bloom中提出。它可以用于檢索一個元素是否在一個集合中,其優點是空間效率和查詢時間都遠遠超過其他算法,其不足在于Bloom- Filter存在著誤判。
二、 Bloom-Filter的基本思想。
?????? Bloom-Filter算法的核心思想就是利用多個不同的Hash函數來解決“沖突”。? 計算某元素x是否在一個集合中,首先能想到的方法就是將所有的已知元素保存起來構成一個集合R,然后用元素x跟這些R中的元素一一比較來判斷是否存在于集合R中;我們可以采用鏈表等數據結構來實現。但是,隨著集合R中元素的增加,其占用的內存將越來越大。試想,如果有幾千萬個不同網頁需要下載,所需的內存將足以占用掉整個進程的內存地址空間。即使用MD5,UUID這些方法將URL轉成固定的短小的字符串,內存占用也是相當巨大的.
?????? 日常生活中,包括在設計計算機軟件時,我們經常要判斷一個元素是否在一個集合中。比如在字處理軟件中,需要檢查一個英語單詞是否拼寫正確(也就是要判斷它是否在已知的字典中);在 FBI,一個嫌疑人的名字是否已經在嫌疑名單上;在網絡爬蟲里,一個網址是否被訪問過等等。最直接的方法就是將集合中全部的元素存在計算機中,遇到一個新元素時,將它和集合中的元素直接比較即可。
????? 一般來講,計算機中的集合是用哈希表(hash table)來存儲的。它的好處是快速準確,缺點是費存儲空間。當集合比較小時,這個問題不顯著,但是當集合巨大時,哈希表存儲效率低的問題就顯現出來了。
三、 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 自帶的
??? private BitSet bits = new BitSet(defaultSize);
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));}}總結
以上是生活随笔為你收集整理的bloom filter 的Java 版的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle AWR 介绍
- 下一篇: HttpClient 学习整理