关于java:如何从唯一字符串生成唯一int? 您所在的位置:网站首页 字符串转换成int 关于java:如何从唯一字符串生成唯一int?

关于java:如何从唯一字符串生成唯一int?

2024-03-05 16:46| 来源: 网络整理| 查看: 265

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

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

10倍

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

相关讨论 你不能只有那么多的int值,但是无限多的字符串。因此,并非每个字符串都可以有自己的int hascode。不过,您可以计算一个唯一的BigInteger哈希码。 @Ingo,我看不到BigIntegers可用作哈希码的许多用途。它们往往太大了。 @Jon,的确如此。字符串本身可能是人们可以获得的几乎最紧凑的键。我添加BigInteger想法只是为了完整性。 不,建议在各处使用哈希码,并由几个标准容器隐式使用。如果您有特定的原因不将其用于给定的问题,请对其进行详细说明,否则人们将不知道为什么不仅仅使用Java字符串哈希码后面的漂亮代码。 规则1:如果JDK已经提供了东西,请不要自己写东西。 JDK代码一直在更新,因此仅通过更新到较新的Java版本,您可能会获得性能更好的实现。如果您自己编写它,它不仅会比JDK提供的东西差很多(在这里是真实的:它是您与整个Sun / Oracle程序员团队的对比),并且您承担了维护它的负担。不要尝试变得聪明,只需执行String.hashCode()。您想优化代码,代码中还有很多其他地方可能会从优化中受益。

不,您不需要"明显地"返回唯一值的实现,因为显然大多数实现都会被破坏。

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

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

编辑:对位的良好传播。

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

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

我们还希望通过不花太多时间来计算哈希来平衡这一点,以至于哈希本身就成为了瓶颈。不完美的平衡行为。

不良哈希方法的一个典型示例是针对X,Y整数的坐标对执行以下操作:

1return X ^ Y;

尽管这样做非常好,可以从4 ^ 32个可能的输入中返回2 ^ 32个可能的值,但在现实世界中,使用X和Y相等的坐标集({0,0},{1 ,1},{2,2}等)都将散列为零,或者匹配对({2,3}和{3,2})将散列为相同的数字。我们最好通过以下方式为我们服务:

1return ((X 16)) ^ Y;

现在,与前者相比,存在许多令人恐惧的可能值,但在现实世界中,它往往会更好。

当然,如果您正在编写通用类(不知道有什么可能的输入)或对手头的目的有更好的了解,则还有另一项工作。例如,如果我使用的是Date对象,但知道它们都只是日期(时间部分始终为午夜),并且彼此之间的间隔只有几年,那么我可能更喜欢只使用日,月和年的低位数,超过标准的一位。 Date的作者虽然无法处理此类知识,但必须尝试迎合所有人。

因此,例如,如果我知道给定的字符串将始终由[az]或[0-9]范围内的6个不区分大小写的字符组成(您的情况似乎如此,但是从您的问题尚不清楚然后,我可能会使用一种算法,为每个字符分配一个0到35(每个字符可能的36个值)的值,然后遍历字符串,每次将当前值乘以36并加上下一个字符。

假设id分布良好,这将是解决问题的方法,特别是如果我按以下顺序进行排序:哈希中的低位数字与id中最频繁更改的char匹配(如果可以进行此调用) ,因此可以很好地将重新哈希处理到较小的范围内。

但是,由于肯定缺乏这种格式的知识,我无法确定地进行该调用,并且可能会使情况变得更糟(算法变慢,散列质量几乎没有或什至是负增益)。

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

相关讨论 +1指出hascodes在定义上不是唯一的。 您能否详细说明"在各个部分之间具有良好的分布"。我不明白那部分/ 嘿,非常感谢。那很有趣。由于我真的不知道我的分布范围是多少,或者最经常变化的char是什么,因此我将以使用String.hashcode()进行映射为根本。我认为我从这些评论中了解到,这是非常合理的解决方案。如果我的收藏中有任何冲突,我的律师会与您联系。我的律师将在此页面上与所有人联系。同时感谢您的启发。 您的律师可能会指出免责声明,并建议如果有很多冲突(除非集合本身写得不好,否则不会有什么问题),那么应该从重新阅读上面的内容开始,详细检查哈希值;)

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

String.hashCode()不会给您唯一的整数,但是会尽最大努力为您提供基于输入字符串的不同结果。

编辑

您编辑的问题说不建议使用String.hashCode()。这是不正确的,建议您这样做,除非您出于某些特殊原因不使用它。如果您有特殊原因,请提供详细信息。

相关讨论 严格来说不是无限的,但是仍然有大约65536 ^(2 ^ 31)左右(包括使用Unicode非字符和代理的无效组合的那些),因此远远超过20亿。 更改为"几乎无限" :-) 嘿,"无限"是一个强词:) 如果您能想到一种更好的措辞方式,请成为我的客人:-)一旦您一方面达到" 40亿欧元","确实很大"似乎有点虚弱... "真的,真的,真的,很大"吗? ;) 关于将哈希码用于大约20K字符串varchar 255有任何想法吗?够安全吗? + Anmol对于这么少的字符串,仅需10个字节的哈希就足够了。如果要进行标准哈希处理,则可以使用SHA-256并使用32个字节(或十六进制编码的64个字符)。 仅增加5美分,我认为该解决方案对于一般用例来说是一个不错的选择。这时,我根据事件的ID在Android中生成一些计划的通知。(这是firebase提供的唯一字符串)。要删除这些通知,在它们消失之前,我需要这个唯一的ID,因为该ID必须为int,所以该解决方案非常适合我的用例

看来您那里有一个以36为底的数字(a-z + 0-9)。为什么不使用Integer.parseInt(s, 36)将其转换为int?显然,如果唯一ID太多,就不能放入int,但是在那种情况下,您就不能使用唯一整数了,因此需要使用String.hashCode()来做到这一点,接近独特。

相关讨论 使用long而不是int可能值得考虑。 @Peter hashCode()返回int,而不是long。否则我会建议的。 如果仅用于hashCode(),则结果不需要唯一。我假设OP知道这一点。 ;) @彼得·特鲁。难以确定他是否想要一个唯一的整数,或想要一个哈希码。如果只是一个唯一的整数,则值得考虑long甚至BigInteger。 我怀疑他要合而为一。 ;)+1顺位。

除非您的字符串受到某种方式的限制,或者您的整数持有比要转换的字符串更多的位,否则您不能保证其唯一性。

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

用五位二进制数字表示每个字符串字符。 a乘00001 b乘00010等,因此32种组合是可能的,例如,cat可能写为00100 00001 01100,然后将该二进制转换为十进制,例如。这将是4140,因此cat将是4140,类似地,您可以通过先将其转换为二进制并将五位数的二进制数映射到字符串来将cat从4140取回

一种实现方法是为每个字母分配一个值,并在字符串的每个位置分配自己的倍数,即a = 1,b = 2,依此类推,然后将第一位数字(从左至右读取)乘以一个质数,下一个是下一个质数,依此类推,以使最终数字乘以一个大于该数字中可能的子集数量的质数(空格为26 + 1或国会大厦为52 + 1,依此类推)其他支持的字符)。如果将数字映射回第一位数字(最左边的字符),则从唯一字符串映射回第一位或第六位的任何数字(无论第一个字母是什么)都会产生一个唯一值。

Dog可能是30,3(15),101(7)或782,而God 33,3(15),101(4)或482。比生成唯一的字符串更重要的是,如果原始数字在生成时它们很有用。如果要设法克服唯一的可能性,则类似于30(782)对于某些12(782)来说是唯一的,以区别于字符串。狗永远是狗,但永远不会是猫或老鼠。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有