`
zhaohuafei
  • 浏览: 28250 次
文章分类
社区版块
存档分类
最新评论

Bloom Filter的原理及实现

 
阅读更多
Bloom Filter:是一个比特数组,表示具有一定误报率的集合。主要优势在于其大小(比特位个数)为常数且在初始化时被设置,增加更多的元素到一个Bloom Filter 中不会增加它的大小,仅增加误报的概率。一般包含两个方法:add(),contains()。
误报率: r = (1-exp(-kn/m))k ,k = ln(2) * (m/n) , r = 0.6185*(m/n)
——k,散列函数个数
——m,比特个数
——n,被添加的元素个数
比如,存储一千万条URL的集合(n = 10 000 000),每个URL分配8个比特(m/n = 8),将需要10M的Bloom Filter(m = 80 000 000),误报率约为2%。若用Set存储,需要1G的空间。

Bloom Filter的内在表现为一个m个比特位的数组。有k个独立的散列函数,每个散列函数的输入为一个对象,而输出为介于0到m-1之间的一个整数。使用这个输出的整数作为位数组的索引。当添加一个元素到Bloom Filter时,使用散列函数来生成位数组的k个索引。



上图(画的图真难看尴尬,不知道什么工具比较好?)是使用三个散列函数的Bloom Filter中添加了几个对象(x,y,z)的过程。无论以前的状态是什么,比特位都被设置为1,在位数组中的1的个数只能增加。对象(如x,y,z)被确定地散列到数组中的位上,而这些位被设置为1,通过散列并检查那些位置上的比特值,可以查看一个对象是否在这个集合中。

当有一个对象到来时,若要检查它是否已经被加入到Bloom Fiter中,则使用与在添加对象时相同的k个散列函数来生成一个位数组的索引。现在检查是否比特数组中所有的k个比特均为1,是则返回true,否则返回false。若已被添加,则一定返回true,不过,即使此对象从未被添加到这个集合中,与所查询相对应的k个比特也可能都为1,这是因为其他对象的增加会设置这些位,从而导致误报。

用java实现的一个Bloom Filter(Hadoop in Action一书中的实现)。
package cn.zhf.test;
import java.io.BufferedReader;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class BloomFilter<E> {
 private BitSet bs;
 private int bitArraySize = 100000000;
 private int numHashFunc = 6;
 public BloomFilter(){
  bs = new BitSet(bitArraySize);
 }
 
 public void add(E obj){
  int[] indexes = getHashIndexes(obj);
  for(int index : indexes)
   bs.set(index);
 }
 
 public boolean contains(E obj){
  int[] indexes = getHashIndexes(obj);
  for(int index : indexes)
   if(bs.get(index) == false)
    return false;
  return true;
 }
 
 public void union(BloomFilter<E> other){
  bs.or(other.bs);
 }
  /*粗略实现,采用MD5散列作为java随机数生成器的种子并取k个随机数作为索引*/
 public int[] getHashIndexes(E obj){
  int[] indexes = new int[numHashFunc];
  long seed = 0;
  byte[] digest;
  try {
   MessageDigest md = MessageDigest.getInstance("MD5");
   md.update(obj.toString().getBytes());
   digest = md.digest();
   for(int i=0;i<6;i++)
    seed = seed^(((long)(digest[i] & 0xFF)) << (8*i));
  } catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
  }
  Random gen = new Random(seed);
  for(int i=0;i<numHashFunc;i++)
   indexes[i] = gen.nextInt(bitArraySize);
  return indexes;
 }
 
 public void write(DataOutput out) throws IOException{
  int byteArraySize = (int)(bitArraySize / 8);
  byte[] byteArray = new byte[byteArraySize];
  for(int i=0;i<byteArraySize;i++){
   byte nextElement = 0;
   for(int j=0;j<8;j++){
    if(bs.get(8*i+j))
     nextElement |= 1<<j;
   }
   byteArray[i] = nextElement;
  }
  out.write(byteArray);
 }
 
 public void readFileds(DataInput in) throws IOException{
  int byteArraySize = (int)(bitArraySize / 8);
  byte[] byteArray = new byte[byteArraySize];
  in.readFully(byteArray);
  for(int i=0;i<byteArraySize;i++){
   byte nextByte = byteArray[i];
   for(int j=0;j<8;j++){
    if(((int)nextByte & (1<<j)) != 0)
     bs.set(8*i+j);
   }
  }
 }
 public Map<Integer,String> readFile(String filePath){
        BufferedReader br;
        Map<Integer,String> map = new HashMap<Integer,String>();
  try {
   br = new BufferedReader(new InputStreamReader(
           new FileInputStream(filePath)));
   int i = 0;
   for (String line = br.readLine(); line != null; line = br.readLine()) {
             map.put(i++, line);
         }
   br.close();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
        return map;
    }
 public static void main(String[] args) {
  BloomFilter<String> bf = new BloomFilter<String>();
  Map<Integer,String> map = bf.readFile("C:\\Users\\zhf\\Desktop\\test.txt");
  for(Map.Entry<Integer, String> m : map.entrySet())
   bf.add(m.getValue());
  boolean flag = bf.contains("15");
  System.out.println(flag);
 }
}


分享到:
评论

相关推荐

    Bloom Filter概念和原理

    ### Bloom Filter概念与原理 #### 一、Bloom Filter概述 Bloom Filter是一种高效的数据结构,主要用于快速查询一个元素是否存在于一个集合中。它通过牺牲一定的精确度来换取存储空间的极大节省。Bloom Filter的...

    介绍Bloom Filter(布隆过滤器)原理、实现及具体应用

    1. **原理**:Bloom Filter的核心在于它的两个组成部分——位数组和哈希函数。位数组通常被初始化为全0,大小根据预期的元素数量和误判率来设定。哈希函数的数量也会影响误判率,通常选取3-7个不相关的函数。每个...

    leveldb中bloomfilter的优化.pdf

    ElasticBF的基本原理是通过构建多个小型Bloom Filter并与每个SSTable关联,从而实现更精细的过滤和动态调整。这种设计使得系统能够在保持较低误报率的同时,有效地管理内存资源。 #### 构建与调整策略 - **构建:**...

    Python-bloomfilter过滤器

    **Python-bloomfilter过滤器详解** Bloom Filter是一种空间效率极高的概率型数据结构,用于判断一个元素是否在一个集合中。在Python开发中,尤其是在处理大量数据时,Bloom Filter可以有效地节省内存空间,尤其适用...

    java-bloomfilter

    Java 中实现布隆过滤器,通常可以使用开源库Guava提供的`com.google.common.hash.BloomFilter`类。Guava的布隆过滤器提供了灵活的参数配置,包括期望元素数量(expectedInsertions)和错误率(fpp,False Positive ...

    多字段矩阵型bloomfilter(支持砍维度)

    首先,我们要理解Bloom Filter的基本原理。它通过多个哈希函数将元素映射到一个位数组中。每个元素都会通过这些哈希函数得到几个位置,然后在这几个位置上设置位。由于位数组是有限的,当位数组中的某些位置被多次...

    Java版本的BloomFilter (布隆过滤器)

    在Java中,我们可以使用Guava库中的`com.google.common.hash.BloomFilter`类来实现Bloom Filter。Guava提供了几个预定义的哈希函数组合,可以自动调整位数组的大小和哈希函数的数量以达到目标误判率。 ```java ...

    BloomFilter算法

    在`ImprovedBloomFilter`这个文件中,可能包含了优化过的Bloom Filter实现,例如使用更好的哈希函数组合,或者动态调整位数组大小以适应数据规模变化。 **应用领域** Bloom Filter广泛应用于: 1. **缓存系统**:...

    bloom filter(C#版自制布隆过滤器)

    它是由 Burton Howard Bloom 在1970年提出的,主要应用于大数据存储和检索,尤其在数据库、缓存系统和网络搜索等领域有广泛应用。C# 版本的布隆过滤器实现了这一概念,通过使用八种不同的哈希函数来提高准确性和减少...

    硬核 - Redis 布隆(Bloom Filter)过滤器原理与实战.doc

    Redis 布隆(Bloom Filter)过滤器原理与实战 Redis 布隆(Bloom Filter)过滤器是一种space efficient的概率型数据结构,用于判断一个元素是否在集合中。布隆过滤器的原理是,首先分配一块内存空间做bit数组,数组...

    Go-bloom-Bloomfilters在Go中的实现

    **正文** Bloom Filter是一种空间效率极高的概率型数据结构,用于判断一个元素是否...理解和掌握Bloom Filter的原理及Go语言实现,对于从事大数据处理、搜索引擎开发或分布式系统的工程师来说,具有很高的实践价值。

    C语言实现的Bloomfilter算法。.zip

    Bloom Filter是一种空间效率极高的概率型数据结构,用于判断一个元素...以上就是关于C语言实现的Bloom Filter算法的主要知识点,理解这些内容有助于我们掌握Bloom Filter的工作原理,以及如何在实际项目中应用和优化。

    如何使用bloomfilter构建大型Java缓存系统Ja

    在Java中,可以使用开源库如Guava提供的BloomFilter类来实现。首先,需要创建一个BloomFilter实例,指定预期的元素数量和错误率。错误率通常是一个较小的浮点数,如0.01,表示1%的误判率。Guava的BloomFilter构造器...

    LDFD-BloomFilter-master.zip

    4. **False Negatives的避免**:在LDFD-BloomFilter的实现中,可能会使用多个独立的Bloom Filters,每个代表不同时间窗口。这样,即使在某个窗口内出现假阳性,通过多窗口的交叉验证,也能降低漏检LDFs的概率。 5. ...

    bloom filter

    源代码可能会定义一个BloomFilter类,包含初始化、插入和查询等方法,同时实现了多个哈希函数。通过阅读和分析这些代码,我们可以深入理解如何在Delphi中实际应用布隆过滤器算法。 总的来说,布隆过滤器是一种在...

    PHP中实现Bloom Filter算法

    在上述代码中,我们定义了一个`BloomFilter`类,构造函数接受哈希函数的数量和位数组的大小作为参数。`add`方法用于添加元素到Bloom Filter中,它通过循环使用哈希函数来计算多个位置并把它们设置为1。`check`方法...

    Bloom过滤器的C++实现

    Bloom过滤器的工作原理基于多个哈希函数。每个插入的元素会经过k个不同的哈希函数映射到一个固定大小的位数组上,对应位置标记为1。当查询一个元素是否存在时,同样通过这些哈希函数计算位数组的位置,如果所有位置...

    bloom-filter:Java中Bloom过滤器的实现

    在Java中实现布隆过滤器,可以使用Guava库提供的`com.google.common.hash.BloomFilter`类。Guava的BloomFilter提供了创建、添加元素和查询元素的方法,并且支持动态调整过滤器的大小以控制误判率。以下是一个简单的...

Global site tag (gtag.js) - Google Analytics