我正在寻找为特定字符串情况创建哈希码的最有效方法。
我有可以转换为整数的字符串,它们从1到10,000不等,并且它们非常集中在1-600范围内。
我的问题是,在从集合中检索项目以实现其哈希码的性能方面,最有效的方法是什么。
我在想的是:
我可以将字符串转换为整数并使用直接访问表(10.000行的数组) - 这对于检索非常快,但在内存分配方面不是很聪明;
< / LI>我可以将字符串用作字符串并获取它的哈希码(我不必将其转换为整数,但我不知道在冲突方面字符串的哈希码有多高效)
非常感谢任何其他想法。
非常感谢
感谢大家及时回复......
还有另外一个信息,我忘记在此添加。如果我让你知道我的最终目标 - 我甚至不需要哈希表,那就明白了吗?
我只想针对不可变的dictiory验证流。我想检查一下给定的标签是否可能出现在我的消息上。
我将收到一对包含几对tag = value的字符串。我想验证我的应用程序是否必须处理标记。
答案 0 :(得分:1)
您可能需要考虑trie(http://en.wikipedia.org/wiki/Trie)或基数树(http://en.wikipedia.org/wiki/Radix_tree)。无需将字符串解析为整数,或计算哈希代码。你在走绳子的时候走在树上。
编辑:
计算字符串上的哈希码并解析字符串中的整数都涉及遍历整个字符串,然后使用该值作为特定数据结构的查找。其他技术可能涉及同时检查遍历数据结构的字符串WHILE。这可能对要求“其他想法”的海报有价值。
答案 1 :(得分:1)
许多馆藏(例如HashMap)已经应用了补充&#34; rehash&#34;帮助处理糟糕的哈希码算法的方法。例如浏览HashMap.hash()
的源代码。而字符串是非常常见的键,因此您可以确定String.hashCode()是高度优化的。所以,除非你注意到你的hashcode之间有很多冲突,否则我会使用标准代码。
我尝试将0..600的字符串放入HashSet中以查看发生了什么,但是看看有多少条目发生冲突是非常繁琐的。找你自己!如果您真的非常在意,请将源代码从HashMap复制到您自己的类中,编辑它以便您可以访问这些条目(在我查看的Java 6源代码中,这将是transient Entry[] table
,YMMV),并添加计算碰撞的方法。
答案 2 :(得分:0)
如果只有有限的有效值范围,为什么不按照建议将该集合表示为int[10000]
? array[x]
处的值是x
出现的次数。
如果你的字符串表示为十进制整数,那么将它们解析为字符串是一个5迭代循环(最多5位数)和几个加法和减法。也就是说,它非常快。插入元素实际上是O(1),检索是O(1)。所需内存大约为40kb(每个int 4个字节)。
一个问题是不保留插入顺序。也许你不在乎。
也许您可以考虑缓存哈希码,并且只有在自上次调用hashcode()
后您的集合发生更改时才更新它。见Caching hashes in Java collections?
答案 3 :(得分:0)
«在您的应用程序中成为热点的时候插入免责声明,并且可以证明这一点»
整数值本身就是一个完美的哈希函数,你不会得到任何碰撞。但是这种方法存在两个问题:
HashMap
不允许您指定自定义哈希函数。因此,要么您必须实现自己的HashMap
,要么使用包装器对象。HashMap
使用按位而不是模运算来查找存储桶。由于它只是一个面具,这显然会引发一些消息。 java.util.HashMap.hash(int)
试图弥补这一点,但我看到声称这不是很成功。我们再次回到实施您自己的HashMap
。现在这一点,因为你使用整数值作为哈希函数,为什么不使用整数值作为HashMap
中的键而不是字符串?如果您真的想要优化它,您可以编写使用int
而非Integer
键的哈希映射,或使用TIntObjectHashMap中的trove。
如果您真的对找到好的哈希函数感兴趣,我可以推荐Hashing in Smalltalk,只需忽略作者对Java进行搜索的半打页面(免责声明:我知道作者)。