出于性能原因,我需要将一组由字符串标识的对象拆分成组。对象可以用数字或带有前缀(限定)形式的字符串来标识,其中的点用于分隔标识符的部分:
12
323
12343
2345233
123123131
ns1:my.label.one
ns1:my.label.two
ns1:my.label.three
ns1:system.text.one
ns2:edit.box.grey
ns2:edit.box.black
ns2:edit.box.mixed
数字标识符从1到数百万。文本标识符最有可能以相同的名称空间前缀(ns1 :)和相同的路径前缀(edit.box。)开头。
为此目的,最好的哈希函数是什么?如果我能根据对象标识符统计以某种方式预测存储桶的大小,那将是很好的。是否有一些好的文章可以根据一些统计信息构建好的哈希函数?
有数百万个这样的标识符,但目的是根据哈希函数将它们分成1-2千组。
答案 0 :(得分:3)
两个好的哈希函数都可以映射到相同的值空间,并且通常不会因组合它们而导致任何新问题。
所以你的哈希函数看起来像这样:
if it's an integer value:
return int_hash(integer value)
return string_hash(string value)
除非你的整数围绕以模N为模的某些值,其中N是可能的桶数,否则int_hash
只能返回其输入。
挑选字符串哈希不是一个新问题。尝试“djb2”(http://www.cse.yorku.ca/~oz/hash.html)或类似内容,除非您有淫秽的性能要求。
我认为修改哈希函数以考虑公共前缀并不重要。如果你的哈希函数是好的开始,那么公共前缀不太可能创建任何哈希值的聚集。
如果你这样做,并且哈希不会意外地执行,并且你将几百万个哈希值放入几千个桶中,那么桶数将是正常分布的,均值(几百万/几千) )和方差1/12(几千)^ 2
每个桶平均有1500个条目,这使得标准偏差大约为430.正态分布的95%位于平均值的2个标准差内,因此95%的桶将包含640-2360个条目,除非我做错了我的总和。这是足够的,还是你需要更紧密相似的尺寸?
答案 1 :(得分:0)
您可能会安全地使用sha1
并将其截断为您想要的任何大小。
它不会非常有效,但哈希函数可能不会成为瓶颈吗?
答案 2 :(得分:0)
我认为CRC16对于这些字符串来说是一个合理的哈希,并且这些组不应该超过1-2千。
这应该使哈希表大约为1MB +但是你有多少项目* 4个字节,所以我们说的是50MB,然后你还要存储所有实际数据,最好是非常小。 / p>