Scala使用MurmurHash3实现简单的BloomFilter

       布隆过滤器用于检测某个值是否已经存在,应用场景很广泛,比如在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.BitSet
import 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))
  }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值