布隆過濾器
簡介:本質上布隆過濾器是一種數據結構,比較巧妙的概率型數據結構(probabilistic data structure),特點是高效地插入和查詢,可以用來告訴你 “某樣東西一定不存在或者可能存在”
判斷一個元素是不是在一個集合里,一般想到的是將所有元素保存起來,然后通過比較來確定。鏈表、平衡二叉樹、散列表,或者是把元素放到數組或鏈表里,都是這種思路。以上三種結構的檢索時間復雜度分別為O(n), O(logn), O(n/k),O(n),O(n)。而布隆過濾器(Bloom Filter)也是用於檢索一個元素是否在一個集合中,它的空間復雜度是固定的常數O(m),而檢索時間復雜度是固定的常數O(k)。相比而言,有1%誤報率和最優值k的布隆過濾器,每個元素只需要9.6個比特位--無論元素的大小。這種優勢一方面來自於繼承自數組的緊湊性,另外一方面來自於它的概率性質。1%的誤報率通過每個元素增加大約4.8比特,就可以降低10倍
應用場景:主要是解決大規模數據下不需要精確過濾的場景,如檢查垃圾郵件地址,爬蟲URL地址去重,解決緩存穿透問題等。
在緩存穿透問題上,使用布隆過濾器判斷數據是否存在,不存在直接返回
海量數據去重:爬蟲系統中對成千上萬的url的去重等
郵箱系統的垃圾郵件過濾功能
實際測試代碼
import java.util.ArrayList; import java.util.List; import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; public class Bloom { private static int size = 1000000; // private static BloomFilter<CharSequence> bloomFilter = // BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")), private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.0001); public static void main(String[] args) { for (int i = 0; i < size; i++) { bloomFilter.put(i); } System.out.println("write over!"); for (int i = 0; i < size; i++) { if (!bloomFilter.mightContain(i)) { System.err.println("有逃犯越獄了"); } } List<Integer> list = new ArrayList<Integer>(); for (int i = size + 10000; i < size + 20000; i++) { if (bloomFilter.mightContain(i)) { list.add(i); } } System.out.println("誤傷數:" + list.size()); } // 可能存在誤判,當布隆過濾器說某個值存在時,這個值可能不存在;當它說不存在時,那就肯定不存在 }
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.0-jre</version>
</dependency>
