BitMap與 Bloom Filter

 一、問題引入  

  bitMap是位圖,其實準確的來說,翻譯成基於位的映射,舉一個例子,有一個無序有界int數組{1,2,5,7},初步估計佔用內存4*4=16字節,這倒是沒什麼奇怪的,但是假如有10億個這樣的數呢?10億*4字節/(1024*1024*1024)=3.72G左右(1GB=1024MB 、1MB=1024KB 、1KB=1024B 、1B=8b)。如果這樣的一個大的數據做查找和排序,那估計內存也崩潰了,有人說,這些數據可以不用一次性加載,那就是要存盤了,存盤必然消耗IO。我們提倡的是高性能,這個方案直接不考慮。

 二、問題分析

  如果用BitMap思想來解決的話,就好很多,解決方案如下:
  一個byte是佔8個bit,如果每一個bit的值就是有或者沒有,也就是二進制的0或者1,如果用bit的位置代表數組值有還是沒有, 那麼0代表該數值沒有出現過,1代表該數組值出現過。不也能描述數據了嗎?具體如下圖:

 Guava中的Bloom Filter使用示例:

int expectedInsertions = ...; //待檢測元素的個數
double fpp = 0.03; //誤判率(desired false positive probability)
BloomFilter<CharSequence> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("UTF-8")), expectedInsertions,fpp);
bloomFilter.put()
bloomFilter.mightContain()

 

但是 BitMap 也有一些侷限,因此會有其它一些基於 BitMap 的算法出現來解決這些問題。

  • 數據碰撞。比如將字符串映射到 BitMap 的時候會有碰撞的問題,那就可以考慮用 Bloom Filter 來解決,Bloom Filter 使用多個 Hash 函數來減少衝突的概率。
  • 數據稀疏。又比如要存入(10,8887983,93452134)這三個數據,我們需要建立一個 99999999 長度的 BitMap ,但是實際上只存了3個數據,這時候就有很大的空間浪費,碰到這種問題的話,可以通過引入 Roaring BitMap 來解決。

Bloom Filter優點

它的優點是空間效率和查詢時間都遠遠超過一般的算法,布隆過濾器存儲空間和插入/查詢時間都是常數O(k)。另外, 散列函數相互之間沒有關係,方便由硬件並行實現。布隆過濾器不需要存儲元素本身,在某些對保密要求非常嚴格的場合有優勢。

Bloom Filter缺點

布隆過濾器的缺點和優點一樣明顯,誤算率(假陽性 False Positive Probability)是其中之一,因爲存在hash 碰撞。

另外,一般情況下不能從布隆過濾器中刪除元素(布隆過濾器的變種Counting bloom filter可以存在刪除元素,思路:在該字段加計數器,當計數器數字爲0時 該位修改爲0)。我們很容易想到把位數組變成整數數組,每插入一個元素相應的計數器加 1,這樣刪除元素時將計數器減掉就可以了。然而要保證安全地刪除元素並非如此簡單。首先我們必須保證刪除的元素的確在布隆過濾器裏面,而這一點單憑這個過濾器是無法保證的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章