在clojure中构建bloom过滤器时要使用哪种散列技术?

时间:2012-03-04 10:07:00

标签: java clojure hash bloom-filter

我想在Clojure中构建一个bloom过滤器,但我对基于JVM的语言可用的所有哈希库知之甚少。

在Clojure中,我应该使用什么来实现最快(而不是最准确)的bloom map实现?

2 个答案:

答案 0 :(得分:11)

查看Apache Cassandra中的Bloom Filter实现。这使用非常快的MurmurHash3算法,并以不同的方式组合两个哈希(或相同哈希的两个部分,因为升级到MurmurHash3而不是MurmurHash2)来计算所需的哈希数。

组合生成方法在this paper

中描述

这是Cassandra源代码的片段:

    long[] hash = MurmurHash.hash3_x64_128(b, b.position(), b.remaining(), 0L);
    long hash1 = hash[0];
    long hash2 = hash[1];
    for (int i = 0; i < hashCount; ++i)
    {
        result[i] = Math.abs((hash1 + (long)i * hash2) % max);
    }

另见Bloomfilter and Cassandra = Why used and why hashed several times?

答案 1 :(得分:3)

所以关于布隆过滤器的有趣之处在于,为了有效地工作,他们需要多个哈希函数。

Java Strings已经内置了一个哈希函数,您可以使用 - String.hashCode()返回一个32位整数哈希。对于大多数用途来说,它是一个OK哈希码,这可能就足够了:例如,如果你将它分成2个独立的16位哈希码,那么这可能足以使你的布隆过滤器工作。你可能会遇到一些碰撞,但这很好 - 布隆过滤器预计会有一些碰撞。

如果没有,你可能想要自己动手,在这种情况下我建议使用String.getChars()来访问原始字符数据,然后使用它来计算多个哈希码。

让你开始的Clojure代码(只是总结字符值):

(let [s "Hello"
      n (count s)
      cs (char-array n)]
  (.getChars s 0 n cs 0)
  (areduce cs i v 0 (+ v (int (aget cs i)))))
=> 500

注意使用Clojure的Java互操作来调用getChars,并使用areduce来对字符数组进行非常快速的迭代。

您可能也对我在Github上发现的Java bloom过滤器实现感兴趣:https://github.com/MagnusS/Java-BloomFilter。哈希码实现乍一看看起来还不错,但它使用了一个字节数组,我觉得它比使用字符的效率低一些,因为需要处理字符编码开销。