網(wǎng)上有很多的原理解釋說明,此處不再對bloom filter做過多的說明,直接上代碼(注:代碼參考了網(wǎng)上其他博客的實現(xiàn),比如布隆過濾器(Bloom Filter)Java實現(xiàn))
- /**
- * 項目名:SpiderCrawler
- * 文件名:BloomFilterTest.java
- * 作者:zhouyh
- * 時間:2014-8-29 下午02:54:56
- * 描述:TODO(用一句話描述該文件做什么)
- */
- package com.utilTest;
-
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.util.BitSet;
-
- /**
- * 類名: BloomFilterTest
- * 包名: com.utilTest
- * 作者: zhouyh
- * 時間: 2014-8-29 下午02:54:56
- * 描述: 布隆過濾器,傳統(tǒng)的布隆過濾器不支持從集合中刪除成員
- */
- public class BloomFilterTest {
- //DEFAULT_SIZE為2的29次方,即此處的左移28位
- private static final int DEFAULT_SIZE = 2<<28;
- /*
- * 不同哈希函數(shù)的種子,一般取質(zhì)數(shù)
- * seeds數(shù)組共有8個值,則代表采用8種不同的哈希函數(shù)
- */
- private int[] seeds = new int[]{3, 5, 7, 11, 13, 31, 37, 61};
- /*
- * 初始化一個給定大小的位集
- * BitSet實際是由“二進制位”構(gòu)成的一個Vector。
- * 假如希望高效率地保存大量“開-關(guān)”信息,就應(yīng)使用BitSet.
- */
- private BitSet bitSets = new BitSet(DEFAULT_SIZE);
- //構(gòu)建hash函數(shù)對象
- private SimpleHash[] hashFuns = new SimpleHash[seeds.length];
- //布隆過濾器配置文件存放路徑
- private String path = "";
-
- public BloomFilterTest(String path){
- /**
- * 給出所有的hash值,共計seeds.length個hash值。共8位。
- * 通過調(diào)用SimpleHash.hash(),可以得到根據(jù)8種hash函數(shù)計算得出hash值。
- * 傳入DEFAULT_SIZE(最終字符串的長度),seeds[i](一個指定的質(zhì)數(shù))即可得到需要的那個hash值的位置。
- */
- for(int i=0; i<seeds.length; i++){
- hashFuns[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);
- }
- //配置文件路徑地址
- this.path = path;
- }
- /**
- *
- * 方法名:add
- * 作者:zhouyh
- * 創(chuàng)建時間:2014-8-30 下午02:07:35
- * 描述:將給定的字符串標記到bitSets中,即設(shè)置字符串的8個函數(shù)值的位置為1
- * @param value
- */
- public synchronized void add(String value){
- for(SimpleHash hashFun : hashFuns){
- bitSets.set(hashFun.hash(value), true);
- }
- }
- /**
- *
- * 方法名:isExit
- * 作者:zhouyh
- * 創(chuàng)建時間:2014-8-30 下午02:12:30
- * 描述:判斷給定的字符串是否已經(jīng)存在在bloofilter中,如果存在返回true,不存在返回false
- * @param value
- * @return
- */
- public synchronized boolean isExit(String value){
- //判斷傳入的值是否為null
- if(null == value){
- return false;
- }
-
- for(SimpleHash hashFun : hashFuns){
- if(!bitSets.get(hashFun.hash(value))){
- //如果判斷8個hash函數(shù)值中有一個位置不存在即可判斷為不存在Bloofilter中
- return false;
- }
- }
-
- return true;
- }
-
- /**
- *
- * 方法名:init
- * 作者:zhouyh
- * 創(chuàng)建時間:2014-8-30 下午02:28:49
- * 描述:讀取配置文件
- */
- public void init(){
- File file = new File(path);
- FileInputStream in = null;
- try {
- in = new FileInputStream(file);
- long lt = System.currentTimeMillis();
- read(in);
- System.out.println(System.currentTimeMillis()-lt);
- System.out.println(Runtime.getRuntime().totalMemory());
- }catch(Exception e){
- e.printStackTrace();
- }finally{
- try {
- if(in!=null){
- in.close();
- in = null;
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
-
- /**
- *
- * 方法名:read
- * 作者:zhouyh
- * 創(chuàng)建時間:2014-8-30 下午02:26:59
- * 描述:根據(jù)傳入的流,初始化bloomfilter
- * @param in
- */
- private void read(InputStream in){
- if(null == in){ //如果in為null,則返回
- return;
- }
-
- int i = 0;
- InputStreamReader reader = null;
-
- try {
- //創(chuàng)建輸入流
- reader = new InputStreamReader(in, "UTF-8");
- BufferedReader buffReader = new BufferedReader(reader, 512);
- String theWord = null;
- do {
- i++;
- theWord = buffReader.readLine();
- //如果theWord不為null和空,則加入Bloomfilter中
- if(theWord!=null && !theWord.trim().equals("")){
- add(theWord);
- }
- if(i%10000 == 0){
- System.out.println(i);
- }
-
- } while (theWord != null);
-
- } catch (IOException e){
- e.printStackTrace();
- } finally{
- //關(guān)閉流
- try {
- if(reader != null){
- reader.close();
- reader = null;
- }
- if(in != null){
- in.close();
- in = null;
- }
- } catch (IOException e) {
- // TODO: handle exception
- e.printStackTrace();
- }
-
- }
- }
-
- /**
- * 方法名:main
- * 作者:zhouyh
- * 創(chuàng)建時間:2014-8-29 下午02:54:56
- * 描述:TODO(這里用一句話描述這個方法的作用)
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- BloomFilterTest bloomFilterTest = new BloomFilterTest("f:/fetchedurls.txt");
- bloomFilterTest.init();
-
- System.out.println(bloomFilterTest.isExit("http://www.plating.org/news_info.asp?pid=28&id=2857"));
- }
-
- public static class SimpleHash {
- /*
- * cap為DEFAULT_SIZE,即用于結(jié)果的最大字符串的值
- * seed為計算hash值的一個key值,具體對應(yīng)上文中的seeds數(shù)組
- */
- private int cap;
- private int seed;
- /**
- *
- * 構(gòu)造函數(shù)
- * 作者:zhouyh
- * @param cap
- * @param seed
- */
- public SimpleHash(int cap, int seed){
- this.cap = cap;
- this.seed = seed;
- }
- /**
- *
- * 方法名:hash
- * 作者:zhouyh
- * 創(chuàng)建時間:2014-8-30 下午01:47:10
- * 描述:計算hash的函數(shù),用戶可以選擇其他更好的hash函數(shù)
- * @param value
- * @return
- */
- public int hash(String value){
- int result = 0;
- int length = value.length();
- for(int i=0; i<length; i++){
- result = seed*result + value.charAt(i);
- }
-
- return (cap-1) & result;
- }
- }
-
- }
實際使用中,效果還不錯,主要用在了爬蟲(crawler)對網(wǎng)址的判重上
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。