web-dev-qa-db-ja.com

hashCode()を使用した文字列の同等性のテスト

Java文字列がhashCodeメソッドを使用して等しいかどうかをテストできない理由はありますか?基本的には...ではなく。

"hello".equals("hello")

あなたが使うことができます...

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

文字列がハッシュコードを計算したら、文字列を比較することは、文字列がハッシュコードをキャッシュするのと同じくらい効率的であり、文字列が文字列プールにある可能性が非常に高いため、これは便利です。仕方。

22
Andy

理由:オブジェクトが等しい場合、2つのオブジェクトのhashCodesは等しくなければなりませんが、2つのオブジェクトが等しくない場合でも、hashCodeは等しい可能性があります。

(コメント後に変更)

37
dstibbe

反例を挙げましょう。これを試して、

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
38
ZZ Coder

多くの人がhashCodeは一意性を保証しないと言っています。実際、それは非常に単純な理由でそれを行うことはできません。

hashCodeはintを返します。これは、2 ^ 32の可能な値(約4,000,000,000)があることを意味しますが、確かに2 ^ 32を超える可能性のある文字列があることを意味します。つまり、少なくとも2つの文字列が同じハッシュコード値を持ちます。

これは 鳩の巣原理 と呼ばれます。

15
Omry Yadan

他の人はそれがうまくいかない理由を指摘しています。とにかくゲインが最小になるという補遺を追加します。

Javaで2つの文字列を比較する場合、String equals関数は、最初に、それらが同じオブジェクトへの2つの参照であるかどうかをチェックします。その場合、すぐにtrueを返します。次に、長さが等しいかどうかを確認します。そうでない場合は、falseを返します。そうして初めて、文字ごとの比較が開始されます。

メモリ内のデータを操作している場合、同じオブジェクトの比較は「同じ」ケースをすばやく処理する可能性があります。これは、簡単な4バイト整数の比較だと思います。 (オブジェクトハンドルの長さが間違っている場合、誰かが私を訂正します。)

ほとんどの等しくない文字列の場合、長さを比較するとすぐに等しくないことがわかります。顧客、都市、製品など、2つの名前を比較する場合、通常、長さは等しくありません。したがって、単純なint比較により、それらはすぐに破棄されます。

パフォーマンスの最悪のケースは、2つの長く、同一であるが、同じオブジェクト文字列ではないことです。次に、オブジェクトハンドルの比較、false、チェックを続ける必要があります。長さの比較、本当、チェックを続けてください。次に、文字列の全長にわたって文字ごとに、はい、実際に最後まで等しいことを確認します。

8
Jay

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
_
4
finnw

HashCode値は一意ではありません。つまり、文字列が実際には一致しない可能性があります。パフォーマンスを向上させるために、equalsの実装では、より面倒なチェックを実行する前に、hashCodeチェックを実行することがよくあります。

1
Jim Rush

非常に単純な理由:衝突のリスク...ハッシュコードは、文字列よりも可能な値がはるかに少なくなります。生成するハッシュの種類によって異なりますが、非常に単純な例を見てみましょう。ここでは、文字の序数にその位置を掛けたものを追加します: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 and .Netこのような衝突の可能性がはるかに少ない、より複雑なハッシュアルゴリズムを使用します。ただし、2つの異なる文字列が同じハッシュ値になる可能性があるため、この方法は次のようになります。信頼性が低くなります。

1
Wim ten Brink

2つの異なる文字列は、同じハッシュコードまたは異なるハッシュコードを簡単に生成できます。同等性テストハッシュが必要な場合、コードは一意の結果を提供しません。 Stringクラスを使用すると、異なる値のハッシュコードが返されます。したがって、文字列バッファクラスを適用して、連結されたすべてのオブジェクトに同じハッシュコードを設定する必要があります。

0