是否存在hashCode恰好等于Integer.MIN_VALUE的Java字符串?
答案是肯定的,存在Java String的hashCode()恰好等于Integer.MIN_VALUE(即-2147483648),并且可以仅由ASCII字符(0-127范围内的字符)组成。
为什么这个场景重要
在哈希表实现中,常见的错误是先对hashCode()调用Math.abs()再取余计算桶索引。但Integer.MIN_VALUE的绝对值仍然是它本身(因为int类型的取值范围是-2^31到2^31-1,无法表示2^31),如果直接对这个值取余,会得到负数索引,进而引发数组越界或错误的桶定位问题,所以这个测试用例能有效暴露这类bug。
构造思路
String的hashCode计算规则是:
s[0] * 31^(n-1) + s[1] * 31^(n-2) + ... + s[n-1]
其中n是字符串长度,s[i]是对应字符的ASCII值。我们可以通过反向推导构造字符串:从Integer.MIN_VALUE出发,每次找到一个ASCII字符c,使得(currentHash - c)能被31整除,然后将currentHash更新为(currentHash - c)/31,重复此过程直到currentHash变为0(此时可以停止,因为空字符串的hashCode是0)。
一个ASCII字符串示例
通过上述方法构造的一个符合要求的ASCII字符串是:"\u001D<[zlynxk vY;<\u001E"(其中包含几个ASCII控制字符,但均属于0-127范围)。如果需要全可见ASCII字符,也可以通过相同逻辑构造出类似"lynxkvY;{z..."的字符串(具体可通过代码验证)。
验证代码
可以用以下Java代码验证任意字符串的hashCode:
public class TestHash { public static void main(String[] args) { String s = "\u001D<[zlynxk vY;<\u001E"; System.out.println(s.hashCode() == Integer.MIN_VALUE); // 输出true } }
内容的提问来源于stack exchange,提问作者John Tang Boyland

