从MurmurHash迁移到MurmurHash3

时间:2013-02-10 12:01:25

标签: scala hash murmurhash

在Scala 2.10中,MurmurHash由于某种原因被弃用,说我现在应该使用MurmurHash3。但API不同,MurmurHash3 - >没有有用的标量。失败。

例如,当前代码:

trait Foo {
  type Bar
  def id: Int
  def path: Bar

  override def hashCode = {
    import util.MurmurHash._
    var h = startHash(2)
    val c = startMagicA
    val k = startMagicB
    h = extendHash(h, id, c, k)
    h = extendHash(h, path.##, nextMagicA(c), nextMagicB(k))
    finalizeHash(h)
  }
}

我如何使用MurmurHash3代替?这需要是一个快速的操作,最好没有分配,所以我不想构建一个ProductSeqArray[Byte]或者MurmurHash3似乎在提供给我。

2 个答案:

答案 0 :(得分:7)

MurmurHash3 algorithm被混淆地从一个混合在自己的盐中的算法(基本上是ck)改变为只进行更多比特混合的算法。基本操作现在是mix,你应该折叠你的所有值,之后你应该finalizeHashInt长度的参数也是为了方便,以帮助区分集合不同的长度)。如果您希望将mix替换为mixLast,则会更快一些,并使用finalizeHash删除冗余。如果您需要花费太长时间才能检测到最后一个混音,只需mix

通常,对于一个集合,您需要混合一个额外的值来指示它是什么类型的集合。

你最低限度

override def hashCode = finalizeHash(mixLast(id, path.##), 0)

和“通常”你

// Pick any string or number that suits you, put in companion object
val fooSeed = MurmurHash3.stringHash("classOf[Foo]")   

// I guess "id" plus "path" is two things?
override def hashCode = finalizeHash(mixLast( mix(fooSeed,id), path.## ), 2)

请注意,长度字段不是为了提供混合在该数字中的高质量哈希。所有重要哈希值的混合都应该使用mix

答案 1 :(得分:4)

看看MurmurHash3的source code建议如下:

override def hashCode = {
  import util.hashing.MurmurHash3._

  val h = symmetricSeed // I'm not sure which seed to use here
  val h1 = mix(h, id)
  val h2 = mixLast(h1, path ##)
  finalizeHash(h2, 2)
}

或,(几乎)一行:

import util.hashing.MurmurHash3._
override def hashCode = finalizeHash(mix(mix(symmetricSeed, id), path ##), 2)