布隆过滤器java实现

来源:互联网 发布:人工智能弹钢琴 编辑:程序博客网 时间:2024/05/01 21:34

网上有很多的原理解释说明,此处不再对bloom filter做过多的说明,直接上代码(注:代码参考了网上其他博客的实现,比如布隆过滤器(Bloom Filter)Java实现)

/**  * 项目名: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 * 描述: 布隆过滤器,传统的布隆过滤器不支持从集合中删除成员 */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;}/** *  * 方法名:add * 作者:zhouyh * 创建时间:2014-8-30 下午02:07:35 * 描述:将给定的字符串标记到bitSets中,即设置字符串的8个函数值的位置为1 * @param value */public synchronized void add(String value){for(SimpleHash hashFun : hashFuns){bitSets.set(hashFun.hash(value), true);}}/** *  * 方法名:isExit * 作者:zhouyh * 创建时间:2014-8-30 下午02:12:30 * 描述:判断给定的字符串是否已经存在在bloofilter中,如果存在返回true,不存在返回false * @param value * @return */public synchronized boolean isExit(String value){//判断传入的值是否为nullif(null == value){return false;}for(SimpleHash hashFun : hashFuns){if(!bitSets.get(hashFun.hash(value))){//如果判断8个hash函数值中有一个位置不存在即可判断为不存在Bloofilter中return false;}}return true;}/** *  * 方法名:init * 作者:zhouyh * 创建时间: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 blocke.printStackTrace();}}}/** *  * 方法名:read * 作者:zhouyh * 创建时间:2014-8-30 下午02:26:59 * 描述:根据传入的流,初始化bloomfilter * @param in */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);}if(i%10000 == 0){System.out.println(i);}} 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 exceptione.printStackTrace();}}}/** * 方法名:main * 作者:zhouyh * 创建时间:2014-8-29 下午02:54:56 * 描述:TODO(这里用一句话描述这个方法的作用) * @param args */public static void main(String[] args) {// TODO Auto-generated method stubBloomFilterTest 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,即用于结果的最大字符串的值 * seed为计算hash值的一个key值,具体对应上文中的seeds数组 */private int cap;private int seed;/** *  * 构造函数 * 作者:zhouyh * @param cap * @param seed */public SimpleHash(int cap, int seed){this.cap = cap;this.seed = seed;}/** *  * 方法名:hash * 作者:zhouyh * 创建时间:2014-8-30 下午01:47:10 * 描述:计算hash的函数,用户可以选择其他更好的hash函数 * @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)对网址的判重上

0 0