布隆過濾器[1](Bloom Filter)是由布隆在1970年提出的。它實際上是由一個很長的二進制向量和一系列隨機映射函數組成,布隆過濾器可以用於檢索一個元素是否在一個集合中,優點是空間效率和查詢時間都遠超一般算法,缺點是有一定的誤識別率(即布隆過濾器報告某一元素在集合中,實際上該元素不在集合中)和刪除困難,但是沒有識別錯誤的情形,如果某個元素確實沒有在該集合中,那麼Bloom Filter是不會>報告該元素存在於集合中的,所以不會漏報
我們通過下面例子來說明其工作原理:
假定我們要存儲1億個網址,假設每個網址需要16個字節存儲,
1. 我們先建立16億二進制常量(Bit Array),並將這16億位全部置成0;
2. 對於每個網址,我們用8個哈希函數產生8個信息指紋(其實就是8個整數);
3. 然後將這8個信息指紋映射到1~16億中的8個自然數中記作(g1,g2,….,g8)將這8個位置的二進制數置成1;
4. 然後每個這樣的網址都進行一遍這樣的處理。
最後針對這些網址的布隆過濾器就建成了。
現在我們看看布隆過濾器如何進行查找該網址是否存在與布隆過濾器中,
(1).首先得到要查找的網址;
(2).同樣用這8個哈希函數產生8個信息指紋;
(3).然後根據這8個信息指紋得到這1~16億中的8個位置;
(4).如果這8個位置上全部爲1,則該網址已經存在;
(5).如果有一個爲0,則表明該網址不存在;
下面我們來看Bloom Filter過濾器的java實現:
package com.xkang.common;
import java.util.BitSet;
public class BloomFilter {
private static int DEFAULT_SIZE = 2<<24;//2G大小
private static int basicIndex = DEFAULT_SIZE-1;
private static final int[] seeds = new int[]{7,11,13,31,37,61};
//位集,創建一種特殊類型的數組來保存位值
private BitSet bits = new BitSet(DEFAULT_SIZE);
/**
* hash函數的主要功能是返回一個0~basicIndex的數
* @param value
* @param seed
* @return
*/
public int hash(String value,int seed){
int result = 0;
int len = value.length();
for(int i=0;i<len;i++){
//hash映射
result = seed*result+value.charAt(i);
}
//將hash出來的散列值映射到0~basicIndex中的某一個數上
return basicIndex&result;
}
//將url添加到布隆過濾器中
public void add(String value){
if(exist(value)){
System.out.println("已經存在布隆過濾器中了");
return;
}
for(int i=0;i<seeds.length;i++){
int index = hash(value,seeds[i]);
//將對應位置上的數置成true;
bits.set(index, true);
}
}
//判斷是否url存在布隆過濾器中;
public boolean exist(String value) {
if(value ==null){
return false;
}
boolean flag=true;
for(int i=0;i<seeds.length;i++){
int index = hash(value,seeds[i]);
flag = flag&&bits.get(index);
}
return flag;
}
/*
*從布隆過濾器中刪除制定url
*這是布隆過濾器的一個缺點,因爲 你不能保證是否有其他url也是用的這個位置,所以當你
*將當前url所對應的位置置0時,可能會導致其他本應該存在的url也被你刪除
*/
public void delete(String value){
if(value == null||!exist(value)){
return ;
}
for(int i=0;i<seeds.length;i++){
int index = hash(value,seeds[i]);
bits.set(index, false);
}
}
}