從上一篇能夠得知,BloomFilter的關鍵在於hash算法的設定和bit數組的大小肯定,經過權衡獲得一個錯誤機率能夠接受的結果。java
算法比較複雜,也不是咱們研究的範疇,咱們直接使用已有的實現。算法
google的guava包中提供了BloomFilter類,咱們直接使用它來進行一下簡單的測試。數組
新建一個maven工程,引入guava包maven
<dependencies> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>22.0</version> </dependency> </dependencies> 測試分兩步:
一 咱們往過濾器裏放一百萬個數,而後去驗證這一百萬個數是否能經過過濾器,目的是校驗是壞人是否必定被抓。函數
二 咱們另找1萬個不在這一百萬範圍內的數,去驗證漏網之魚的機率,也就是布隆過濾器的誤傷狀況。測試
import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; import java.util.ArrayList; import java.util.List; /** * Created by admin on 17/7/7. * 布隆過濾器 */ public class Test { private static int size = 1000000; private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size); public static void main(String[] args) { for (int i = 0; i < size; i++) { bloomFilter.put(i); } for (int i = 0; i < size; i++) { if (!bloomFilter.mightContain(i)) { System.out.println("有壞人逃脫了"); } } List<Integer> list = new ArrayList<Integer>(1000); for (int i = size + 10000; i < size + 20000; i++) { if (bloomFilter.mightContain(i)) { list.add(i); } } System.out.println("有誤傷的數量:" + list.size()); } }
運行後發現,沒有壞人逃脫,當咱們去遍歷這一百萬個數時,他們都在過濾器內被識別了出來。google
誤傷的數量是330.也就是有330個不在過濾器內的值,被認爲在過濾器裏,被誤傷了。圖片
錯誤機率是3%做用,爲毛是3%呢。咱們跟蹤源碼看一下就知道了。內存
在create的多個重載方法中,最終走的是有4個參數的那個。咱們上面用的是有2個參數的,注意看圖片最下面,咱們不填第三方參數時,默認補了一個0.03,這個就表明了容許的錯誤機率是3%。第四個參數是哈希算法,默認是BloomFilterStrategies.MURMUR128_MITZ_64,這個咱們不去管它,反正也不懂。ci
在第127行能夠看到,要存下這一百萬個數,位數組的大小是7298440,700多萬位,實際上要完整存下100萬個數,一個int是4字節32位,咱們須要4X8X1000000=3千2百萬位,差很少只用了1/5的容量,若是是HashMap,按HashMap 50%的存儲效率,咱們須要6千4百萬位,全部布隆過濾器佔用空間很小,只有HashMap的1/10-1/5做用。
128行是hash函數的數量,是5,也就是說系統以爲要保證3%的錯誤率,須要5個函數外加700多萬位便可。用3%偏差換十分之一的內存佔用。
咱們也能夠修改這個錯誤機率,譬如咱們改成0.0001萬分之一。
private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.0001);
再次運行看看
咱們將28行改成10萬個數,發現結果爲「誤傷12」。能夠看到這個機率是比較靠譜的。
當機率爲萬分之一時,咱們看看空間佔用。
此時bit容量已經從700多萬到1900萬了,函數數量也從5變成了13.機率從3%縮減到萬分之一。
這就是布隆過濾器的簡單使用。具體的應用場景,具體實現。