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

20 篇文章 0 订阅

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

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


假定我们存储一亿个电子邮件地址,我们先建立一个十六亿二进制(比特),即两亿字节的向量,然后将这十六亿个二进制位全部设置为零。对于每一个电子邮件地址 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值