是否可以使用java的哈希码函数为不同的字符串使用相同的哈希码?或者如果可能的话,它的可能性百分比是多少?
答案 0 :(得分:58)
Java哈希码是32位。它散列的可能字符串数量是无限的。
是的,会有碰撞。百分比毫无意义 - 存在无限数量的项(字符串)和有限数量的可能哈希值。
答案 1 :(得分:22)
YES。很多。
看下面的一对
可以返回相同的哈希码,即使其中的字符不相同。
基本上它是字符串中字符的总和乘以整数。
答案 2 :(得分:8)
如果有可能那么它的可能性百分比是多少?
这不是一个特别有意义的问题。
但是,除非String::hashcode
函数或生成String
对象的方式存在某些系统偏差,否则任何两个不同(不相等)String
的概率对象将具有相同的哈希码,将为1 in 2 32 。
这假定从所有可能的String值集合中随机选择字符串。如果以各种方式限制集合,则概率将与上述数字不同。 (例如,“FB”/“Ea”碰撞的存在意味着所有2个字母串的集合中的碰撞概率高于标准。)
另外需要注意的是,没有哈希冲突的随机选择的2 32 不同字符串的机会是消失小。要了解原因,请阅读Birthday Paradox上的维基百科页面。
实际上,如果您选择或生成字符串,唯一的方法就是在一组2个 32 不同字符串中获得无哈希冲突。即使通过选择随机生成的字符串来形成集合也将是计算上昂贵的。要有效地生成这样的集合,您需要利用String::hashCode
算法的属性(幸运的是)。
答案 3 :(得分:8)
是的,完全有可能。字符串(或其他一些对象类型 - 假设您将使用此示例中的字符串)与集合中的其他字符串具有相同哈希码的概率取决于该集合的大小(假设所有该集合中的字符串是唯一的)。概率分布如下:
所做的假设是:
此网站清楚地解释了这一点:http://eclipsesource.com/blogs/2012/09/04/the-3-things-you-should-know-about-hashcode/ (看看"你应该知道的第二件事")
答案 4 :(得分:6)
这不会直接回答你的问题,但我希望它有所帮助。
以下内容来自java.lang.String
。
/**
* Returns a hash code for this string. The hash code for a
* <code>String</code> object is computed as
* <blockquote><pre>
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* </pre></blockquote>
* using <code>int</code> arithmetic, where <code>s[i]</code> is the
* <i>i</i>th character of the string, <code>n</code> is the length of
* the string, and <code>^</code> indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
*/
public int hashCode() {
int h = hash;
int len = count;
if (h == 0 && len > 0) {
int off = offset;
char val[] = value;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
答案 5 :(得分:5)
是的,两个字符串可能具有相同的哈希码 - 如果您查看Wikipedia article,您会发现"FB"
和"Ea"
具有相同的哈希码。方法合同中没有任何内容表示应使用hashCode()
来比较相等性,您希望使用equals()
。
自Java 1.2起,String通过using a product sum algorithm over the entire text of the string实现hashCode()
。
答案 6 :(得分:4)
是的,根据鸽子洞概念的定义,两个不同的字符串可以产生相同的哈希码,并且应该始终编写代码以满足这些条件(通常不会破坏。)
答案 7 :(得分:2)
随机字符串的冲突百分比应该是最小的。但是,如果您从外部源散列字符串,攻击者可以轻松创建数十万个具有相同哈希码的字符串。在Java HashMap中,这些都将映射到同一个存储桶,并有效地将地图转换为链接列表。然后,地图的访问时间将与地图大小成比例而不是常数,从而导致拒绝服务攻击。
有关演示文稿的更多信息,请参阅Effective DoS attacks against Web Application Plattforms上的此页面。
答案 8 :(得分:2)
是的,这是可能的,因为equals()&amp;之间的合同之一。 Object类的hashCode()方法是.......... 如果两个对象根据equals()方法不相等,则无法保证其hashCode相同,hashCode可能/可能不相等。 即,如果obj1.equals(obj2)返回false,则obj1.hashCode()== obj2.hashCode()可能/可能不返回true。 例如:
String str1 = "FB";
String str2 = "Ea";
System.out.println(str1.equals(str2));// false
System.out.println(str1.hashCode() == str2.hashCode()); // true
答案 9 :(得分:0)
//您可以使用-Xmx2100m运行以下代码,并且可以获得多个结果,足以填满您的控制台
`
import java.util.HashMap;
public class TestHashCollision {
public static void main(String[] args) {
final String TEXT = "was stored earlier had the same hash as";
HashMap<Integer,String> hs=new HashMap<>();
long t1=System.currentTimeMillis();
long t2=System.currentTimeMillis();
for(long l=0;l<Long.MAX_VALUE;l++) {
String key="d"+l;
if(hs.containsKey(key.hashCode())) {
System.out.println("'"+hs.get(key.hashCode())+"' "+TEXT+" '"+key+"'");//System.exit(0);
} else {
hs.put(key.hashCode(),key);
}
t2=System.currentTimeMillis();
if(t2-t1>10000) {
t1=System.currentTimeMillis();
System.out.println("10 seconds gone! size is:"+hs.size());
}
}
System.out.println("Done");
}
}
`
答案 10 :(得分:0)
是的(不仅仅是Java,它适用于任何语言),它可以为不同的字符串生成相同的哈希码。 我想起了我教授教授的一条规则,在这里可能有用-
两个相同的字符串/值必须具有相同的哈希码,但反之则不成立。
python中的示例
>>> hash('same-string')
-5833666992484370527
>>> hash('same-string')
-5833666992484370527
可能还有另一个字符串可以匹配相同的哈希码,因此我们不能使用哈希码来导出密钥。
答案 11 :(得分:-2)
nativeQuery = true
java哈希函数在此处返回相等的值。