通过"非空",我的意思是在这个问题上至少包含一个非零字符的字符串。
作为参考,下面是hashCode
实现:
1493 public int hashCode() {
1494 int h = hash;
1495 if (h == 0) {
1496 int off = offset;
1497 char val[] = value;
1498 int len = count;
1499
1500 for (int i = 0; i < len; i++) {
1501 h = 31*h + val[off++];
1502 }
1503 hash = h;
1504 }
1505 return h;
1506 }
并且算法在文档中指定。
在整数溢出发生之前,答案很简单:是否定的。但我想知道的是,由于整数溢出,非空字符串的哈希码是否可能为零?你能建造一个吗?
理想情况下,我正在寻找的是数学演示(或指向一个的链接)或构造算法。
当然。例如,字符串 f5a5a608 的哈希码为零。
我通过简单的蛮力搜索发现:
public static void main(String[] args){
long i = 0;
loop: while(true){
String s = Long.toHexString(i);
if(s.hashCode() == 0){
System.out.println("Found: '"+s+"'");
break loop;
}
if(i % 1000000==0){
System.out.println("checked: "+i);
}
i++;
}
}
编辑:在JVM上工作的Joseph Darcy甚至编写了一个程序,该程序可以通过基本上反向运行哈希算法来构造具有给定哈希码的字符串(以测试开关/案例语句中字符串的实现)。
只是要注意那个int h;
。它可能会溢出,每个满足h % 2^31 == 0
的字符串都可能导致这种情况。
public class HelloWorld {
public static void main(String []args) {
System.out.println("u0001!qbygvW".hashCode());
System.out.println("9 $Ql(0".hashCode());
System.out.println(" #t(}lrl".hashCode());
System.out.println(" !!#jbw}a".hashCode());
System.out.println(" !!#jbw|||".hashCode());
System.out.println(" !!!!Se|aaJ".hashCode());
System.out.println(" !!!!"xurlls".hashCode());
}
}
很多字符串...
下面是查找和打印任何所需hashCode
值的字符串的代码:
public static int findIntInverse(int x) {
// find the number y such that as an int (after overflow) x*y = 1
// assumes x is odd, because without that it isn't possible.
// works by computing x ** ((2 ** 32) - 1)
int retval = 1;
for (int i = 0; i < 31; i++) {
retval *= retval;
retval *= x;
}
return retval;
}
public static void findStrings(
int targetHash,
Iterable<String> firstParts,
Iterable<String> midParts,
Iterable<String> lastParts) {
Map<Integer, String> firstHashes = new HashMap<>();
for (String firstPart : firstParts) {
firstHashes.put(firstPart.hashCode(), firstPart);
}
int maxlastlen = 0;
int maxmidlen = 0;
for (String midPart : midParts) {
maxmidlen = Math.max(midPart.length(), maxmidlen);
}
for (String lastPart : lastParts) {
maxlastlen = Math.max(lastPart.length(), maxlastlen);
}
List<Integer> hashmuls = new ArrayList<>();
String baseStr = "u0001";
for (int i = 0; i <= maxmidlen + maxlastlen; i++) {
hashmuls.add(baseStr.hashCode());
baseStr += "