我在基于java的系统中工作,我需要为可视显示中的某些元素设置id。一类元素是字符串,所以我决定使用String.hashCode()方法来获取这些元素的唯一标识符。
然而,我遇到的问题是,如果id为负数且String.hashCode
经常返回负值,我在borks工作的系统。一个快速的解决方案是在hashcode调用周围使用Math.abs()来保证肯定的结果。我对这种方法感到疑惑的是两个不同元素具有相同哈希码的可能性是什么?
例如,如果一个字符串返回的哈希码为-10,另一个字符串返回的哈希码为10,则会发生错误。在我的系统中,我们讨论的是通常不超过30个元素的对象集合,所以我不认为这确实是一个问题,但我很好奇数学所说的。
答案 0 :(得分:11)
哈希码可以被认为是伪随机数。统计上,使用正int
哈希码,当群体大小约为54K时,任何两个元素之间发生冲突的可能性达到50%(任何 int
为77K)。有关各种哈希码大小的冲突概率,请参阅Birthday Problem Probability Table。
此外,您单独使用Math.abs()
的想法存在缺陷:它并不总是返回正数!在2的恭维算术中,Integer.MIN_VALUE
的绝对值本身就是!众所周知,"polygenelubricants"
的哈希码就是这个值。
答案 1 :(得分:7)
哈希不是唯一的,因此它们不适合 uniqueId 。
关于哈希冲突的可能性,您可以阅读birthday paradox。实际上(根据我的记忆)从N值的均匀分布绘制时,你应该在绘制$ \ sqrt(N)$之后发生碰撞(你可以更早地得到碰撞)。问题是Java的hashCode
实现(特别是散列短字符串时)并不能提供统一的分布,所以你会更早地发生碰撞。
答案 2 :(得分:3)
您已经可以获得具有相同哈希码的两个字符串。如果您认为您拥有无限数量的字符串且只有2 ^ 32个可能的哈希码,那么这应该是显而易见的。
在获取绝对值时,你可能会更有可能。风险很小但如果你需要一个唯一的ID,这不是正确的方法。
答案 3 :(得分:1)
当您只有30-50个值时,您可以执行的操作是将每个字符串与运行计数器一起注册到HashMap中作为值:
HashMap StringMap = new HashMap<String,Integer>();
StringMap.add("Test",1);
StringMap.add("AnotherTest",2);
然后,您可以通过以下方式获取您的唯一ID:
StringMap.get("Test"); //returns 1