Java中最快的字符串哈希算法
Posted
技术标签:
【中文标题】Java中最快的字符串哈希算法【英文标题】:Fastest Hash algorithm in Java for Strings 【发布时间】:2015-10-27 07:14:27 【问题描述】:为了简单起见,我的问题是:如何尽快散列一个字符串(大约 200 个字符)。安全性不重要,但碰撞很重要。
注意:经过快速调查,似乎MurmurHash3 可能是最佳选择。我愿意接受任何评论,否则'
首先,我知道还有很多其他类似的问题,但我还没有找到令人信服的答案。
我有一个对象列表,每个对象都包含一个保存到数据库的大约 3k 段落的列表。每隔 X 小时,这些段落就会重新生成,我需要查找是否有任何段落发生了变化,如果是,则只推送那些新段落。
我发现找到差异的最快方法(知道大部分时间内容是相同的)是创建一个MerkleTree,将其保存到数据库,然后遍历 MerkleTree 以查找差异,而不是比较段落本身。
这意味着,就我而言,我将每秒创建一万个哈希值来与数据库中的哈希值进行比较。因此,我需要一种非常有效的方法来创建这些哈希。我不关心安全性,我只需要确保碰撞次数保持非常非常低。
Java 中最好的算法是什么?
在我的例子中,主要对象由 Sections 组成,Sections 由 Languages 组成,Languages 由 Paragraph 组成。比较策略是:
1)如果对象hash相同则停止,否则转2)
2) 循环所有Section,只保留具有不同哈希的Section
3) 循环这些部分的所有语言,只保留具有不同哈希的语言
4) 循环所有这些语言的所有段落,如果哈希不同,则推送新内容。
【问题讨论】:
见:Which hashing algorithm is best for uniqueness and speed? 我觉得这个问题不太清楚,您是否只需要确定一个 specific 对象段落是否已更改或者是 find 哪个对象的想法一个段落属于(即主键是什么?)。 也看看***.com/questions/2624192/… @slartidan 不幸的是,该链接仅推荐了一些基本的哈希算法,对于像 OP 似乎存在严重性能问题的人来说,这还不够。 【参考方案1】:This amazing answer on Programmers Stack Exchange tells you all you need to know.
短版是,使用FNV-1a, aka the Fowler–Noll–Vo hash function,它具有出色的性能,高随机性和低碰撞。
我可能对这个问题的任何进一步解释都只是从 Programmers.SE 答案中复制和粘贴,顺便说一句,这是整个网站上投票第二高的答案。
其他一些想法:
最终,您有一个非常适合的用例。大多数人不会定期处理 10 亿个条目数据集。因此,您可能必须自己进行基准测试。 也就是说,具有高随机性表明该算法很可能适用于英文哈希。 您还没有真正谈论过其他问题;你能把整个数据集保存在内存中吗?您的足迹要求是什么?另见:Fastest Hash Algorithm for Text Data
【讨论】:
听起来很酷,但在只有 250k 的数据集上看到碰撞让我有点失望。需要明确的是,碰撞对我来说很重要,我有超过 10 亿个条目。在查看具有超过 2^128 种可能性的算法时,您不会期望在如此小的数据集上发生任何冲突? 如果你考虑碰撞的原因,这很正常。冲突发生在单字数据上,因此数据实际上非常紧凑,发生冲突是正常的。数据越大,碰撞越少。你说你有完整的段落,在你拥有的前 250k 段落上测试算法,并在你的实际上下文中检查冲突,而不是在那个人的特定上下文中。 我愿意买那个。话虽如此,您是否解释了为什么较短的 String 会有更多的碰撞机会,或者这只是一个理论? 对于正确完成的哈希,哈希值应该大于哈希大小。你说你想散列文本。文本通常定义为 26 个字符(小写)+ 26 个字符(大写)+ 标点和空格(+/- 10 个字符)。这大约是 6 位熵。如果您的散列有 64 位空间,为了使您的散列相关,您需要至少 11 个字符 (ceil(64/6)
)。链接中的那个人在字典上做了他的测试。我敢肯定 90% 的单词少于 11 个字符。所以他的测试擅长测试速度。但是测试真正的哈希分布?没有。熵太少了。
我不会写任何答案:它本身不会回答问题,但感谢您的赞赏;)以上是关于Java中最快的字符串哈希算法的主要内容,如果未能解决你的问题,请参考以下文章