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

时间:2009-09-23 12:14:39

标签: java string hashcode

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

"hello".equals("hello")

你可以使用......

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

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

9 个答案:

答案 0 :(得分:37)

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

(评论后修改)

答案 1 :(得分:37)

让我举一个反例。试试这个,

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

答案 2 :(得分:15)

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

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

这称为Pigeonhole principle

答案 3 :(得分:8)

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

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

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

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

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

答案 4 :(得分:4)

您可以使用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

答案 5 :(得分:1)

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

答案 6 :(得分:1)

非常简单的原因:碰撞的风险...... 哈希码的值可能比字符串少得多。它取决于你生成的哈希类型,但让我们举一个非常简单的例子,你可以在其中添加字母的序数值,乘以它的位置:a = 1,b = 2等等。因此,'你好'会翻译成: h:8x1 = 8,e:5x2 = 10,l:12x3 = 36,l:12x4 = 48,o:15x5 = 75。 8 + 10 + 36 + 48 + 75 = 177。

是否有其他字符串值可能以177散列结束?当然!很多选择。随意计算一些。

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

答案 7 :(得分:0)

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

答案 8 :(得分:-2)

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

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