Scala使用MurmurHash3实现简单的BloomFilter

来源:互联网 发布:java rpc实现 编辑:程序博客网 时间:2024/04/29 09:13

       布隆过滤器用于检测某个值是否已经存在,应用场景很广泛,比如在Hbase中可以在ROW(行级)或ROWCOL(行+列)两个级别配置是否开启布隆过滤器。其作用是反向检测某个数据是否存在于某个数据块,检测结果确定为不存在或不确定。只有对不存在的判断是确切的,因为BloomFilter对存在的判断具有一定的误判率。BloomFilter将待处理的数据经过N个hash函数映射到一个Bit数组的N个值,hash值则为Bit数组的索引项。经过处理,如果一个值已经存在,那么必定满足Bit[Hi] == true 其中i为1到N,Hi为使用第i个hash函数得到的hash值,Bit为位数组。

       在实现一般的网络爬虫的时候也可以考虑添加BloomFilter功能来过滤已爬取的网页。下面的代码为使用Scala util包下的MurmurHash3实现的BloomFilter。

import java.util.BitSetimport scala.util.hashing.MurmurHash3/**  * 实现简单的bloomfilter过滤器,用来判断某个url是否已经被爬取  */object BloomFilter {  /** 1 << 24位长度的位图数组,存放hash值*/  val bitSetSize = 1 << 32  /**位数组*/  val bitSet = new BitSet(bitSetSize)  /**传入murmurhash中的seed的范围*/  val seedNums = 6    /**    * 根据MurmurHash3计算哈希值,设置BitSet的值    * @param str    */  def hashValue(str: String): Unit = {    if(str != null && !str.isEmpty)      for(i <- 1 to seedNums) bitSet.set(Math.abs(MurmurHash3.stringHash(str, i)) % bitSetSize, true)     else      println("传入的字符串位空")  }  /**    * 判断一个字符串是否存在于bloomFilter    * @param str    * @return    */  def exists(str: String): Boolean = {    def existsRecur(str: String, seed: Int): Boolean = {      if(str == null || str.isEmpty) false      else if(seed > seedNums) true      else if(!bitSet.get(Math.abs(MurmurHash3.stringHash(str, seed)) % bitSetSize)) false      else existsRecur(str, seed + 1)    }    if(str == null || str.isEmpty)      false    else      existsRecur(str, 1)  }  def main(args: Array[String]) = {    val s1 = "www.baidu.com"    val s2 = "www.jd.com"    val s3 = "www.taobao.com"    val s4 = "http://kafka.apache.org"    BloomFilter.hashValue(s1)    BloomFilter.hashValue(s2)    BloomFilter.hashValue(s3)    BloomFilter.hashValue(s4)    println(BloomFilter.exists(s1))    println(BloomFilter.exists(s2))    println(BloomFilter.exists(s3))    println(BloomFilter.exists(s4))  }}