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位

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

使用bloomfilter的更多相关文章

  1. BloomFilter 与 Cuckoo Filter

    BloomFilter 与 CuckooFilter Bloom Filter 原理 Bloom Filter是一种空间效率很高的随机数据结构,它的原理是,当一个元素被加入集合时,通过K个相互独立的H ...

  2. Hbase中的BloomFilter(布隆过滤器)

    (1)     Bloomfilter在hbase中的作用 Hbase利用bloomfilter来提高随机读(get)的性能,对于顺序读(scan)而言,设置Bloomfilter是没有作用的(0.9 ...

  3. [转]BloomFilter——大规模数据处理利器

    Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法.通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合. 一. 实例 为了说明Bl ...

  4. 基于Redis的BloomFilter算法去重

    BloomFilter算法及其适用场景 BloomFilter是利用类似位图或者位集合数据结构来存储数据,利用位数组来简洁的表示一个集合,并且能够快速的判断一个元素是不是已经存在于这个集合.因为基于H ...

  5. BloomFilter–大规模数据处理利器(转)

    BloomFilter–大规模数据处理利器 Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法.通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求1 ...

  6. BloomFilter——读数学之美札记

    之前接触过bitmap,读吴军先生的数学之美,看到了一个更强大的数据结构,布隆过滤器(Bloomfilter),赶紧记下来吧,忘了怪可惜的. bitmap的使用是很有局限性的,往往只能用于海量数值型数 ...

  7. BloomFilter算法

    Bloom filter 是由 Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员.如果检测结果为是,该元素不一定 ...

  8. 关于在Python下安装布隆过滤器(bloomfilter)的方法

    由于在爬虫代码中需要实现信息的去重功能,所以需借助bloomfilter,在看完各种博客后发现没有安装,这就尴尬了,不会连门都找不到吧.那就安装呗,各种错误,查看官方文档:http://axiak.g ...

  9. 布隆过滤器(BloomFilter)持久化

    摘要 Bloomfilter运行在一台机器的内存上,不方便持久化(机器down掉就什么都没啦),也不方便分布式程序的统一去重.我们可以将数据进行持久化,这样就克服了down机的问题,常见的持久化方法包 ...

  10. BloomFilter(布隆过滤器)

    原文链接:http://blog.csdn.net/qq_38646470/article/details/79431659 1.概念: 如果想判断一个元素是不是在一个集合里,一般想到的是将所有元素保 ...

随机推荐

  1. leetcode240 搜索二维矩阵 II

    题目: 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target.该矩阵具有以下特性: 每行的元素从左到右升序排列. 每列的元素从上到下升序排列. 示例: 现有矩阵 ma ...

  2. redis和mongodb面试题(一)

    ● 请你回答一下mongodb和redis的区别 参考回答: 内存管理机制上:Redis 数据全部存在内存,定期写入磁盘,当内存不够时,可以选择指定的 LRU 算法删除数据.MongoDB 数据存在内 ...

  3. kubeDNS workflow(service registration and discovery)

    Service discovery In k8s, we usually will more than make an application instance, and also the corre ...

  4. linux下测试web访问及网络相关的命令

    curl命令 curl是linux系统命令行下用来简单测试web访问的工具. curl -xip:port www.baidu.com    -x可以指定ip和端口,省略写hosts,方便实用 -I  ...

  5. Linux系统下C语言获取Time

    获取时间的函数有很多,具体包括如下: time()/gettimeofday()等等,下面是获取具体到usecond的时间程序: #include <iostream> #include ...

  6. Linux中FTP服务器配置

         1.FTP服务器的一些基本概念       (1)FTP连接方式     控制连接:标准端口为21,用于发送FTP命令信息.     数据连接:标准端口为20,用于上传.下载数据.      ...

  7. 17JQuery

    1. 概念 一个JavaScript框架.简化JS开发  jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScrip ...

  8. IDEA Debug模式下启动慢的解决办法

    工程没有做什么大的改动,近期Idea在debug模式下启动耗时800s +,run模式下200s.Idea debug模式启动的时候会有这样的提示: 方法断点会戏剧性的降低debug的速度.当时并没有 ...

  9. pkg-config --libs libusb-1.0

    pkg-config --libs libusb-1.0 pkg-config --libs libusb-1.0 pkg-config --libs libusb-1.0

  10. redis 加锁与释放锁(分布式锁1)

    使用Redis的 SETNX 命令可以实现分布式锁 SETNX key value 返回值 返回整数,具体为 - 1,当 key 的值被设置 - 0,当 key 的值没被设置 分布式锁使用 impor ...