zoukankan      html  css  js  c++  java
  • 使用bloomfilter

    package bloom;
    
    /**
     * 项目名:SpiderCrawler
     * 文件名:BloomFilterTest.java
     * 作者:zhouyh
     * 时间:2014-8-29 下午02:54:56
     * 描述:TODO(用一句话描述该文件做什么) 
     */
    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;
    import java.util.Scanner;
    
    /**
    * 描述: 布隆过滤器,传统的布隆过滤器不支持从集合中删除成员
    */
    public class BloomFilterTest {
    	//DEFAULT_SIZE为2的29次方,即此处的左移28位
    	private static final int DEFAULT_SIZE = 2<<28;
    	/*
    	 * 不同哈希函数的种子,一般取质数
    	 * seeds数组共有8个值,则代表采用8种不同的哈希函数
    	 */
    	private int[] seeds = new int[]{3, 5, 7, 11, 13, 31, 37, 61};
    	/*
    	 * 初始化一个给定大小的位集
    	 * BitSet实际是由“二进制位”构成的一个Vector。
    	 * 假如希望高效率地保存大量“开-关”信息,就应使用BitSet.
    	 */
    	private BitSet bitSets = new BitSet(DEFAULT_SIZE);
    	//构建hash函数对象
    	private SimpleHash[] hashFuns = new SimpleHash[seeds.length];
    	//布隆过滤器配置文件存放路径
    	private String path = "";
    	
    	public BloomFilterTest(String path){
    		/**
    		 *  给出所有的hash值,共计seeds.length个hash值。共8位。
    		 *  通过调用SimpleHash.hash(),可以得到根据8种hash函数计算得出hash值。	
    		 *  传入DEFAULT_SIZE(最终字符串的长度),seeds[i](一个指定的质数)即可得到需要的那个hash值的位置。		
    		 */
    		for(int i=0; i<seeds.length; i++){
    			hashFuns[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);
    		}
    		//配置文件路径地址
    		this.path = path;
    	}
    	/**
    	 * 描述:将给定的字符串标记到bitSets中,即设置字符串的8个函数值的位置为1
    	 */
    	public synchronized void add(String value){
    		for(SimpleHash hashFun : hashFuns){
    			bitSets.set(hashFun.hash(value), true);
    		}
    	}
    	/**
    	 * 描述:判断给定的字符串是否已经存在在bloofilter中,如果存在返回true,不存在返回false
    	 */
    	public synchronized boolean isExit(String value){
    		//判断传入的值是否为null
    		if(null == value){
    			return false;
    		}
    		
    		for(SimpleHash hashFun : hashFuns){
    			if(!bitSets.get(hashFun.hash(value))){
    				//如果判断8个hash函数值中有一个位置不存在即可判断为不存在Bloofilter中
    				return false;
    			}
    		}
    		
    		return true;
    	}
    	
    	/**
    	 * 描述:读取配置文件
    	 */
    	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();
    			}
    		}
    	}
    	
    	/**
    	 * 描述:根据传入的流,初始化bloomfilter
    	 */
    	private void read(InputStream in){
    		if(null == in){	//如果in为null,则返回
    			return;
    		}
    		
    		int i = 0;
    		InputStreamReader reader = null;
    		
    		try {
    			//创建输入流
    			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.split("	")[1]);
    //					System.out.println(theWord.split("	")[1]);
    				}
    				if(i%10000 == 0){
    //					System.out.println(i);
    //					System.out.println(theWord.split("	")[1]);
    				}
    				if(i%1000000 == 0){
    					System.out.println(i);
    					break;
    				}
    				
    			} while (theWord != null);
    			
    		} catch (IOException e){
    			e.printStackTrace();
    		} finally{
    			//关闭流
    			try {
    				if(reader != null){
    					reader.close();
    					reader = null;
    				}				
    				if(in != null){
    					in.close();
    					in = null;
    				}
    			} catch (IOException e) {
    				// TODO: handle exception
    				e.printStackTrace();
    			}
    			
    		}
    	}
    	
    	/**
    	 * 描述:TODO(这里用一句话描述这个方法的作用)
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		BloomFilterTest bloomFilterTest = new BloomFilterTest("D:\学习\实验室项目\ImageNet图片爬取\fall11_urls.txt");
    		bloomFilterTest.init();
    		
    		Scanner sc = new Scanner(System.in);   
           
    		while(true){
    			System.out.println("输入网址:");  
    			String s = sc.nextLine();
    			System.out.println(bloomFilterTest.isExit(s));
    		}
    //		test();
    //		System.out.println(Integer.toBinaryString(DEFAULT_SIZE-1));
    	}
    	public static void test(){
    		int tt1 = 2<<28;
    		int tt2 = 2<<29;
    		int tt3 = 2<<30;
    		int tt4 = 2<<1;
    		System.out.println(Integer.toBinaryString(tt1)+" "+Integer.toBinaryString(tt1).length());
    		System.out.println(Integer.toBinaryString(tt2)+" "+Integer.toBinaryString(tt2).length());
    		System.out.println(Integer.toBinaryString(tt3-1)+" "+Integer.toBinaryString(tt3).length());
    		System.out.println(Integer.toBinaryString(tt4)+" "+Integer.toBinaryString(tt4).length());
    		BitSet b = new BitSet(tt3);
    	}
    	public static class SimpleHash {
    		/*
    		 * cap为DEFAULT_SIZE,即用于结果的最大字符串的值
    		 * seed为计算hash值的一个key值,具体对应上文中的seeds数组
    		 */
    		private int cap;
    		private int seed;
    		/**
    		 * 构造函数
    		 */
    		public SimpleHash(int cap, int seed){
    			this.cap = cap;
    			this.seed = seed;
    		}
    		/**
    		 * 描述:计算hash的函数,用户可以选择其他更好的hash函数
    		 */
    		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);
    			}
    			//011..11共32位,故&运算以后可以取后31位
    			return (cap-1) & result;
    		}
    	}
    
    }
    

    此处应该注意Bitset最多只有32位

    根据别人的数据适当选择大小



  • 相关阅读:
    谢惠民,恽自求,易法槐,钱定边编数学分析习题课讲义16.2.3练习题参考解答[来自陶哲轩小弟]
    高考题(可作为试讲资料)
    美国数学教父拒绝10亿美元 免费分享教学视频
    梁启超死亡真相:主刀医生错把健康的肾切除
    [家里蹲大学数学杂志]第418期南开大学2013年实变函数期末考试试题参考解答
    陆启铿同志去世
    [电视剧]养父的花样年华
    [电视剧]错爱一生
    [家里蹲大学数学杂志]第413期插值不等式
    Oracle的 EXEC SQL CONTEXT学习
  • 原文地址:https://www.cnblogs.com/yan456jie/p/5369541.html
Copyright © 2011-2022 走看看