BloomFilter布隆過濾器使用

從上一篇能夠得知,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%縮減到萬分之一。

這就是布隆過濾器的簡單使用。具體的應用場景,具體實現。

相關文章
相關標籤/搜索