在内存中判断海量数据的唯一性

来源:互联网 发布:植物大战丧尸 java 编辑:程序博客网 时间:2024/05/09 14:59

在内存中判断海量数据的唯一性

通过布隆过滤算法来实现了

假定我们存储一亿个电子邮件地址,我们先建立一个十六亿二进制(比特),即两亿字节的向量,然后将这十六亿个二进制位全部设置为零。对于每一个电子邮件地址 X,我们用八个不同的随机数产生器(F1,F2, ...,F8) 产生八个信息指纹(f1, f2, ..., f8)。再用一个随机数产生器 G 把这八个信息指纹映射到 1 到十六亿中的八个自然数 g1, g2, ...,g8。现在我们把这八个位置的二进制位全部设置为一。当我们对这一亿个 email 地址都进行这样的处理后。一个针对这些 email 地址的布隆过滤器就建成了。当 k = ln(2)* m/n (k是hash函数个数,m是bit数组的长度,n是加入值的个数)时出错的概率是最小的。例如:哈希函数个数k取10,位数组大小m设为字符串个数n的20倍时,false positive发生的概率是0.0000889 ,这个概率基本能满足网络爬虫的需求了。  假如k=10,总共有1亿条记录(即n=100 000 000),则需要的字节为m=1.86G(即m=n*20=100 000 000 *20=2 000 000 000=1.86G);以下是C#的布隆算法处理类:public class BloomFilter<T>{    private BitArray _bitArray = null;    private int _count = 0;//n:记录的总条数    private int _hashcount = 1;//k:hash函数的个数    ///<summary>    ///    ///</summary>    ///<param for="size">m:bit数组的长度</param>    ///<param for="hashcount">k:是hash函数个数</param>    public BloomFilter(int size, int hashcount)    {        _bitArray = new BitArray(size, false);        _hashcount = hashcount;    }    public void Add(T item)    {        int h1 = item.GetHashCode();        int h2 = Hash(h1.ToString());        bool result = false;        unchecked       {            h1 = (int)(((uint)h1) % _bitArray.Count);           h2 = (int)(((uint)h2) % _bitArray.Count);       }       for (int i = 0; i < _hashcount; i++)       {          if (!_bitArray[h1])          {              _bitArray[h1] = result = true;          }          unchecked          {              h1 = (int)((uint)(h1 + h2) % _bitArray.Count);              h2 = (int)((uint)(h2 + i) % _bitArray.Count);          }      }      if (result)      {          _count++;      }  } public bool Contains(T item)  {       int h1 = item.GetHashCode();       int h2 = Hash(h1.ToString());       unchecked        {         h1 = (int)(((uint)h1) % _bitArray.Count);          h2 = (int)(((uint)h2) % _bitArray.Count);        }       for (int i = 0; i < _hashcount; i++)       {         if (_bitArray[h1] == false)           {              return false;          }           unchecked           {              h1 = (int)((uint)(h1 + h2) % _bitArray.Count);               h2 = (int)((uint)(h2 + i) % _bitArray.Count);         }        }       return true;   }    protected int Hash(T item)   {       int hashcode = item.GetHashCode();       hashcode = Hash(hashcode.ToString());       return hashcode;   }    /// <summary>   /// 字符串Hash函数(AP Hash Function)    /// </summary>   /// <param name="str">需要Hash的字符串</param>  /// <returns></returns>    protected int Hash(string str)   {       long hash = 0;       for (int i = 0; i < str.Length; i++)       {          if ((i & 1) == 0)           {               hash ^= ((hash << 7) ^ str[i] ^ (hash >> 3));           }          else           {                hash ^= (~((hash << 11) ^ str[i] ^ (hash >> 5)));           }       }       unchecked       {           return (int)hash;       }   }   /// <summary>   /// 记录的总条数   /// </summary>    public int Count    {        get        {            return _count;        }    }    /// <summary>   /// 返回BloomFilter中的bit数组的长度   /// </summary>    public int SizeBytes    {        get        {            return _bitArray.Length;        }    }}

参考:
https://luzhijun.github.io/2016/09/02/%E6%B5%B7%E9%87%8F%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86/

0 0