我想在Clojure中构建一个bloom过滤器,但我对基于JVM的语言可用的所有哈希库知之甚少。
在Clojure中,我应该使用什么来实现最快(而不是最准确)的bloom map实现?
答案 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。哈希码实现乍一看看起来还不错,但它使用了一个字节数组,我觉得它比使用字符的效率低一些,因为需要处理字符编码开销。