如何从唯一字符串生成唯一的int?

2022-09-01 20:18:19

我有一个带有字符串的对象,该对象保存唯一的ID。(例如“ocx7gf”或“67hfs8”)我需要为它提供int hascode()的实现,这显然是唯一的。

我如何以最简单/最快的方式将字符串转换为唯一的int?

10 倍。

编辑 - 确定。我已经知道String.hashcode是可能的。但在任何地方都不建议这样做。实际上,如果不建议使用任何其他方法 - 如果我在集合中有我的对象并且我需要哈希码,我是否应该使用它。我应该将它连接到另一个字符串以使其更成功吗?


答案 1

不,您不需要有一个返回唯一值的实现,“显然”,因为显然大多数实现都会被破坏。

你想做的是,在位之间有一个很好的分布,特别是对于共同的值(如果任何值比其他值更常见)。除非对您的格式有特殊的了解,否则最好只使用字符串本身的哈希码。

通过对id格式限制的特殊了解,可以进行自定义并产生更好的性能,尽管错误的假设更有可能使事情变得更糟而不是更好。

编辑:关于位的良好传播。

正如这里和其他答案中所述,完全唯一是不可能的,并且哈希冲突是可能的。使用哈希的方法知道这一点并且可以处理它,但它确实会影响性能,因此我们希望冲突很少见。

此外,哈希通常被重新散列,因此我们的32位数字最终可能会被减少到例如0到22范围内的一个,我们希望尽可能好地分布在其中。

我们还希望平衡这一点,不要花费太长时间来计算我们的哈希值,以至于它本身就成为瓶颈。一种不完美的平衡行为。

错误哈希方法的一个经典示例是 X,Y 整数的坐标对,它具有以下功能:

return X ^ Y;

虽然这在从4 ^ 32个可能的输入中返回2 ^ 32个可能的值方面做得很好,但在现实世界中使用中,具有X和Y相等的坐标集({0,0},{1,1},{2,2}等)是很常见的,这些坐标集都散列为零,或者匹配对({2,3}和{3, 2}) 将散列到相同的数字。我们可能通过以下方式获得更好的服务:

return ((X << 16) | (x >> 16)) ^ Y;

现在,有许多可能的值比前者可怕,但它往往在现实世界中服务更好。

当然,如果你正在编写一个通用类(不知道有什么可能的输入)或者对手头的目的有更好的了解,那就有不同的工作了。例如,如果我使用Date对象,但知道它们都只是日期(时间部分总是午夜),并且仅在彼此相距几年内,那么我可能更喜欢仅使用年份的日,月和较低数字的自定义哈希代码,而不是标准哈希代码。虽然的作者不能研究这些知识,但必须努力满足每个人的需求。Date

因此,例如,如果我知道一个给定的字符串总是由[a-z]或[0-9]范围内的6个不区分大小写的字符组成(你的似乎是这样,但从你的问题中看不出它是否确实如此),那么我可能会使用一种算法,为每个字符分配一个从0到35的值(每个字符的36个可能值), 然后遍历字符串,每次将当前值乘以 36 并加上下一个字符的值。

假设ids的良好传播,这将是要走的路,特别是如果我的顺序使得我的哈希中较低的有效数字与id中变化最频繁的char相匹配(如果可以进行这样的调用),因此可以很好地重新散列到较小的范围。

但是,由于缺乏对格式的了解,我无法确定地进行该调用,并且我很可能使事情变得更糟(算法较慢,哈希质量几乎没有甚至负增益)。

您拥有的一个优点是,由于它本身就是一个ID,因此可能没有其他不相等的对象具有相同的ID,因此不需要检查其他属性。这并不总是成立的。


答案 2

不能从长度不限的字符串中获取唯一整数。有 40 亿 (2^32) 个唯一整数,但唯一字符串的数量几乎是无限的。

String.hashCode()不会给你唯一的整数,但它会尽最大努力根据输入字符串给你不同的结果。

编辑

您编辑后的问题显示不建议使用 String.hashCode()。这不是真的,建议这样做,除非你有一些特殊的理由不使用它。如果您有特殊原因,请提供详细信息。