1 目的
一個好的過濾算法需要具備的特征有:低時間復雜度、低空間復雜度、低錯誤率。本算法從低時間復雜度(算法只需要讀取一次文件)和空間復雜度出發,通過尋找它們的平衡點以達到低錯誤率。
2 原理
當需要判斷一個元素是不是在一個集合中,我們通常做法是把所有元素保存下來,然后通過比較知道它是不是在集合內,鏈表、樹都是基於這種思路,當集合內元素個數的變大,我們需要的空間和時間都線性變大,檢索速度也越來越慢。 BloomFilter采用的是哈希函數的方法,將一個元素映射到一個m長度的陣列上的一個點,當這個點是 1 時,那么這個元素在集合內,反之則不在集合內。這個方法的缺點就是當檢測的元素很多的時候可能有沖突,解決方法就是使用k個哈希函數對應k個點,如果所有點都是 1 的話,那么元素在集合內,如果有 0 的話,元素則不在集合內。
根據此原理可以推斷出總的誤判個數期望為

具體的證明可以看參考的博客鏈接
假設去重后總量為1億條,可利用內存最大為1G,也就是位數組長度2^33為 ,則可預估如下表結果:
| 假設總量: |
1億 |
|
|
|
|
| Hash個數 |
h=3 |
h=4 |
h=5 |
h=6 |
h=7 |
| 誤判數 |
1022 |
87 |
10 |
2 |
0 |
| 誤判率 |
1.02E-05 |
8.70E-07 |
1.00E-07 |
2.00E-08 |
0.00E+00 |
為此,在執行中只需要將哈希函數的個數設置為7個即可保證很大程度上與真實總量一致.
3 執行步驟

4 算法的改進

與傳統的布隆過濾器相比
優勢:每個字符串只進行一次數值轉換,傳統做法是多個Hash函數產生多個值,我們只產生一個值,利用多Mod對該值取余(等價於多Hash函數),減少多次Hash函數值轉換帶來的運行時間。
劣勢:貌似可以證明與傳統的算法的空間復雜度與准確率均相等,所以暫時說不出啥缺點
對於一個字符串,經過HashCode轉換成對應的數值,分別對K個大素數進行求余操作,並查找對應的小布隆過濾器相對的位置是否為1,如果均為1則該字符串已經包含其中,否則是新字符串,既而對相應的位置數值更改為1.
本人用這套思路在java上實現了,判斷1億條數據,占用內存700M,准確率達100%
具體的實現代碼可查閱本人的Github:
https://github.com/JueFan/BloomFilterTool
參考博客
