美文网首页
布隆过滤器

布隆过滤器

作者: 维特无忧堡 | 来源:发表于2018-07-15 17:13 被阅读0次

    近期学习的时候发现了一个强大的神器,布隆过滤器,发现这个算法对大数据的去重真的很有用哎!记录一下,免得自己忘了。

    概念

      首先我先来介绍一下这个算法的基本思想,假设让你实现查重的话,你肯定是用Hash表存储下来,然后判断,那么怎么存储呢?给你一个字符串,你肯定是先用hash函数映射一下,如果值的访问太大的话,可能要取个模什么的,让后这个作为标识存储在Hash表中,虽然这样做的时间复杂度不高,但空间使用率太高了,而且你想一下,你根本就不用这个串,你只是要知道是否有重复,这样布隆过滤器就诞生了。
      假设我们这边有8个不同hash函数(很完美的),4字节的一个空间(32位)(可以称之为桶),每一位都设置为0,我们分别使用这8个hash函数,然后对32取余,这样就会得到8个小于32位的数字,我们把这八个数字当作序号,把32位中对应的位设置位1,表示已经存在,这样,当我们下次再有相同的字符串的时候,我们可以看看对应位置上是不是都是1,如果是就是重复啦,如果不是就说明不在里面;
      是不是很神奇,对的。那么这个算法有没有局限呢?它是绝对不会漏掉相同的串的(因为相同的串Hash肯定是一样的),有可能会误判,这就是所谓的宁可错杀也不放过,所以说合理选择Hash函数个数很重要
      那么怎么计算这个Hash函数个数呢? 假设整个数据大小是n,容许的失误率是p
    那么 hash函数的个数(我听一个大佬总结的)

    m = n * ln p / (ln 2)^2

    那么这个复杂度是多少呢?还是O(n)啊,判断一个串的话就是O(1),那有的人就奇怪了,判断的话不是应该是O(n)吗?不是的,一个串的唯一表示就是一个32位的空间,相当于一个int的值,就BitSet存储get的话就是O(1)

    代码实现

    接着来一波代码,让大家感受一下

    package Filter;
    
    import java.util.BitSet;
    
    public class BloomFilter {
       private  static  int BIT_SIZE = 2 << 25;//可以表示的数据量 ,你可以试着调大一点
       private BitSet bitSet ;
       private int[] seeds = {3,5,7,11,13,31,37,61};
       private HashFunction[] func;
       public BloomFilter(int size) throws Exception{
           if (size <= 30 && size > 0){
               BIT_SIZE = 2 << size;
           } else {
               throw  new Exception("range illegal");
           }
           bitSet = new BitSet(BIT_SIZE);
           func = new HashFunction[seeds.length];
           for (int i = 0; i < func.length; i++){
               func[i] = new HashFunction(seeds[i],seeds.length);
           }
       }
       public void add(String val){
           if (val == null) return;
           for (HashFunction function : func){
               bitSet.set(function.hash(val),true);
           }
       }
       public boolean contain(String val){
           if (val == null) return false;
           for(HashFunction function: func){
               if(!bitSet.get(function.hash(val)))
                   return false;
           }
           return true;
       }
    
       public static class HashFunction{
           private int seed;
           private int size;
           public HashFunction(int seed,int size){
               this.seed = seed;
               this.size = size;
           }
          //计算hash的方法,我看String源码里面写的是seed = 31,
           public int hash(String value){
               int ans = 0;
               for (char ch : value.toCharArray()){
                   ans = ans * seed + ch;
               }
               return ans & (size - 1);
           }
       }
    }
    
    

    相关文章

      网友评论

          本文标题:布隆过滤器

          本文链接:https://www.haomeiwen.com/subject/grxruftx.html