使用hashCode()测试字符串相等性

是否有任何理由不能使用hashCode方法测试Java字符串的相等性? 所以基本上,而不是….

"hello".equals("hello") 

你可以用……

 "hello".hashCode() == "hello".hashCode() 

这很有用,因为一旦字符串计算出它的哈希码,那么比较一个字符串就像比较一个int一样有效,因为字符串缓存了哈希码,而且很可能字符串在字符串池中,如果你设计它办法。

因为:如果对象相等,则两个对象的hashCodes必须相等,但是,如果两个对象不相等,则hashCode仍然可以相等。

(评论后修改)

让我举个例子。 尝试这个,

 public static void main(String[] args) { String str1 = "0-42L"; String str2 = "0-43-"; System.out.println("String equality: " + str1.equals(str2)); System.out.println("HashCode eqauality: " + (str1.hashCode() == str2.hashCode())); } 

我的Java上的结果,

 String equality: false HashCode eqauality: true 

正如许多人所说,hashCode不保证唯一性。 事实上,由于一个非常简单的原因,它无法做到这一点。

hashCode返回一个int,这意味着有2 ^ 32个可能的值(大约4,000,000,000),但肯定有超过2 ^ 32个可能的字符串,这意味着至少有两个字符串具有相同的哈希码值。

这被称为鸽子原则 。

其他人指出了为什么它不起作用。 所以我只是添加附录,无论如何,收益将是最小的。

在Java中比较两个字符串时,String equals函数首先检查它们是否是对同一对象的两个引用。 如果是这样,它立即返回true。 然后检查长度是否相等。 如果不是,则返回false。 只有这样才开始逐个字符地比较。

如果你正在操作内存中的数据,同一对象比较可以快速处理“相同”的情况,这是一个快速,嗯,4字节整数比较我认为。 (如果对象句柄的长度错误,有人会纠正我。)

对于大多数不相等的字符串,我敢打赌长度比较很快发现它们不相等。 如果您要比较两个名称 – 客户,城市,产品等等 – 它们的长度通常不等。 所以一个简单的int比较快速处理它们。

性能最糟糕的情况是两个长的,相同的,但不是相同的对象字符串。 然后它必须做对象句柄比较,false,继续检查。 长度比较,真实,继续检查。 然后逐个字符地通过字符串的整个长度来validation确实它们确实是一直到最后。

您可以使用String.intern() (使用哈希表实现String.intern()获得所需的效果。

您可以使用==运算符比较intern()的返回值。 如果它们引用相同的字符串,则原始字符串是等效的(即equals()将返回true ),并且它只需要一个指针比较(与int比较具有相同的成本)。

 String a = "Hello"; String b = "Hel" + "lo"; System.out.println(a.equals(b)); System.out.println(a == b); String a2 = a.intern(); String b2 = b.intern(); System.out.println(a2.equals(b2)); System.out.println(a2 == b2); 

输出:

 true false true true 

hashCode值不是唯一的,这意味着字符串可能实际上不匹配。 为了提高性能,通常在执行更费力的检查之前,equals的实现将执行hashCode检查。

非常简单的原因:冲突的风险……哈希代码的值可能比字符串少得多。 它取决于你生成的一点哈希,但让我们举一个非常简单的例子,你可以在其中添加字母的序数值,乘以它的位置:a = 1,b = 2等等。因此,’hello’会转换为:h:8×1 = 8,e:5×2 = 10,l:12×3 = 36,l:12×4 = 48,o:15×5 = 75。 8 + 10 + 36 + 48 + 75 = 177。

还有其他字符串值可能以177散列结束吗? 当然! 很多选择。 随意计算几个。

尽管如此,这种散列方法使用了一种简单的方法。 Java和.NET使用更复杂的散列算法,此类冲突的可能性要小得多。 但是,两个不同的字符串有可能产生相同的哈希值,因此这种方法不太可靠。

两个不同的String可以轻松生成相同的哈希码或不同的哈希码。 如果你想要一个相等的测试哈希代码将不会给出一个独特的结果。 当我们使用String类时,它将返回不同的哈希代码值。 因此,应该应用String缓冲区类,以便为每个连接的对象提供相同的哈希代码。

没有理由不像你描述的那样使用hashCode。

但是,您必须了解碰撞。 有一个机会 – 不可否认的是 – 两个不同的字符串确实散列到相同的值。 首先考虑使用hashCode,如果相等,也使用equals()进行完全比较。