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

我有一个带有String的对象,该String包含唯一的id。 (例如“ocx7gf”或“67hfs8”)我需要为它提供一个int hascode()的实现,这显然是唯一的。

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

10X。

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

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

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

凭借对id格式限制的特殊了解,可以自定义并获得更好的性能,但错误的假设更可能使事情变得更糟。

编辑:在比特的良好传播。

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

此外,散列通常被重新散列,因此我们的32位数可能最终减少到例如0到22之间的一个,并且我们希望尽可能好地分配。

我们还想平衡这一点,而不是花太多时间来计算我们的哈希,它本身就成了一个瓶颈。 不完美的平衡行为。

一个糟糕的哈希方法的典型例子是一个X,Y整数的坐标对象:

return X ^ Y; 

虽然这可以很好地从4 ^ 32个可能的输入中返回2 ^ 32个可能的值,但在实际使用中,使用X和Y相等的坐标集是很常见的({0,0},{1所有散列为零的匹配,或匹配对({2,3}和{3,2})将散列到相同的数字,1},{2,2}等等。 我们可能会更好地服务于:

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

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

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

因此,如果我知道一个给定的字符串总是由[az]或[0-9]范围内的6个不区分大小写的字符组成(你可能会这样,但是你的问题并不清楚然后我可能会使用一个算法,为每个字符分配一个0到35之间的值(每个字符的36个可能值),然后遍历字符串,每次将当前值乘以36并添加值下一个字符。

假设在ID中有一个很好的传播,这将是要走的路,特别是如果我做了这样的命令,使得我的哈希中的较低有效数字与id中最频繁更改的字符匹配(如果可以进行这样的调用)因此可以很好地重新散列到较小范围内。

然而,由于缺乏格式的这种知识,我无法确定地进行调用,而且我可能会使事情变得更糟(对于散列质量很少或甚至负增益的较慢算法)。

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

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

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

编辑

您编辑的问题表明不建议使用String.hashCode()。 除非您有特殊原因不使用它,否则建议不要这样。 如果您有特殊原因,请提供详细信息。

看起来你有一个36号基数(az + 0-9)。 为什么不使用Integer.parseInt(s, 36)将其转换为int? 显然,如果有太多的唯一ID,它将不适合int ,但在这种情况下,你运气不好用于整数,并且需要通过使用String.hashCode() ,它尽力使用接近独特。

除非你的字符串在某种程度上受到限制,或者你的整数比你想要转换的字符串容纳更多的位,否则你不能保证唯一性。

假设您的字符串有32位整数和64个字符的字符集。 这意味着每个字符六位。 这将允许您将五个字符存储为整数。 不仅如此,它也不适合。

一种方法是为每个字母分配一个值,并且它所拥有的字符串的每个位置都是多个,即a = 1,b = 2,依此类推,那么第一个数字中的所有内容(从左到右读取)将乘以素数,下一个素数等等,这样最后的数字乘以一个大于该数字中可能的子集数量的素数(26 + 1代表空格或52 + 1代表资本等等)对于其他支持的字符)。 如果数字被映射回第一个数字(最左边的字符),您将从唯一字符串生成的任何数字映射回1或6,无论第一个字母是什么,都会给出一个唯一值。

狗可能是30,3(15),101(7)或782,而上帝33,3(15),101(4)或482。比生成的唯一字符串更重要的是,如果原始数字,它们可以用于生成保留,像30(782)将是独特的约12(782),以区分相似的字符串,如果你曾设法克服独特的可能性。 狗永远是狗,但它永远不会是猫或老鼠。