web-dev-qa-db-ja.com

JavaのhashCodeは異なる文字列に対して同じ値を生成できますか?

Javaのハッシュコード機能を使用して、異なる文字列に同じハッシュコードを使用することは可能ですか?または可能であれば、その可能性の%は何ですか?

43
Xara

A Javaハッシュコードは32ビットです。ハッシュ文字列の数は無限です。

そうです、衝突があります。割合は無意味です-アイテム(文字列)の数は無限であり、ハッシュの数は有限です。

60
Mat

可能であれば、その可能性の%は何ですか?

それは特に意味のある質問ではありません。

ただし、String::hashcode関数またはStringオブジェクトの生成方法に何らかのシステムバイアスがない限り、2つの異なる(等しくない)Stringオブジェクトが生成される確率同じハッシュコードを持つことになります2に132

これは、可能なすべてのストリング値のセットからストリングがランダムに選択されることを前提としています。セットをさまざまな方法で制限すると、確率は上記の数とは異なります。 (たとえば、「FB」/「Ea」衝突の存在は、2つの文字列すべてのセットでの衝突の確率が標準よりも高いことを意味します。)


もう1つ注意すべきことは、32 ハッシュ衝突を持たないランダムに選択された異なる文字列(文字列のはるかに大きい不偏のセットから)はvanishingly小さいです。理由を理解するには、ウィキペディアのページで 誕生日のパラドックス を読んでください。

実際には、2つのセットでハッシュ衝突を取得しない唯一の方法です。32 異なる文字列は、文字列を選択または生成する場合です。ランダムに生成された文字列を選択してセットを形成することでさえ、計算コストが高くなります。このようなセットを効率的に作成するには、(残念ながら)指定されているString::hashCodeアルゴリズムのプロパティを活用する必要があります。

8
Stephen C

はい、それは完全に可能です。コレクション内の他の文字列と同じハッシュコードを持つ文字列(または、この例では文字列を使用すると仮定する他のオブジェクトタイプ)の確率は、そのコレクションのサイズに依存します(すべての文字列がそのコレクションは一意です)。確率は次のように配布されます。

  • サイズが〜9,000のセットでは、2つの文字列がセット内のハッシュと衝突する可能性が1%になります
  • サイズのセットが30,000を超えると、2つの文字列がセット内のハッシュと衝突する可能性が10%になります
  • サイズが〜77,000のセットでは、50%の確率で2つの文字列がセット内のハッシュと衝突します

前提条件は次のとおりです。

  • HashCode関数にはバイアスはありません
  • 前述のセットの各文字列は一意です

このサイトはそれを明確に説明しています: http://eclipsesource.com/blogs/2012/09/04/the-3-things-you-should-know-about-hashcode/ (「 2番目に知っておくべきこと」)

8
NSV

これはあなたの質問に直接答えるものではありませんが、助けになることを願っています。

以下はJava.lang.Stringのソースコードからのものです。

/**
 * Returns a hash code for this string. The hash code for a
 * <code>String</code> object is computed as
 * <blockquote><pre>
 * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
 * </pre></blockquote>
 * using <code>int</code> arithmetic, where <code>s[i]</code> is the
 * <i>i</i>th character of the string, <code>n</code> is the length of
 * the string, and <code>^</code> indicates exponentiation.
 * (The hash value of the empty string is zero.)
 *
 * @return  a hash code value for this object.
 */
public int hashCode() {
    int h = hash;
    int len = count;
    if (h == 0 && len > 0) {
    int off = offset;
    char val[] = value;

        for (int i = 0; i < len; i++) {
            h = 31*h + val[off++];
        }
        hash = h;
    }
    return h;
}
6
adarshr

はい、2つの文字列が同じハッシュコードを持つことができます- Wikipediaの記事 を見ると、_"FB"_と_"Ea"_の両方が同じであることがわかりますハッシュコード。メソッドコントラクトにはhashCode()を使用して等価性を比較する必要があるとは記載されていません。そのためにequals()を使用する必要があります。

Java 1.2であるため、StringはhashCode()文字列のテキスト全体に対して積和アルゴリズムを使用 で実装します。

5
Marcelo

random文字列の衝突の割合は最小限でなければなりません。ただし、外部ソースから文字列をハッシュすると、攻撃者は同じハッシュコードを持つ数十万の文字列を簡単に作成できます。 Java HashMapでは、これらはすべて同じバケットにマップされ、マップを事実上リンクリストに変換します。マップへのアクセス時間は、定数ではなくマップサイズに比例し、サービス拒否攻撃。

プレゼンテーションへの詳細情報リンクについては、 Webアプリケーションプラットフォームに対する効果的なDoS攻撃 のこのページをご覧ください。

3
Jörn Horstmann

はい、これは可能です。Objectクラスのequals()とhashCode()メソッドの間のコントラクトの1つは.......... If 2つのオブジェクトがequals()メソッドに従って等しくない場合、それらのhashCodeが同じであるという保証はなく、hashCodeは等しくても、等しくなくてもかまいません。 hashCode()はtrueを返す場合とそうでない場合があります。例:

    String str1 = "FB";
    String str2 = "Ea";
    System.out.println(str1.equals(str2));// false
    System.out.println(str1.hashCode() == str2.hashCode()); // true
2
Manish Kumar

//-Xmx2100mを使用して以下のコードを実行すると、複数の結果を取得できます。これは、コンソールを満たすのに十分です

`

import Java.util.HashMap;

public class TestHashCollision {
        public static void main(String[] args) {
        final String TEXT = "was stored earlier had the same hash as";
        HashMap<Integer,String> hs=new HashMap<>();
        long t1=System.currentTimeMillis();
        long t2=System.currentTimeMillis();
        for(long l=0;l<Long.MAX_VALUE;l++) {
            String key="d"+l;
            if(hs.containsKey(key.hashCode())) {
                System.out.println("'"+hs.get(key.hashCode())+"' "+TEXT+" '"+key+"'");//System.exit(0);
            } else {
                hs.put(key.hashCode(),key);
            }
            t2=System.currentTimeMillis();
            if(t2-t1>10000) {
                t1=System.currentTimeMillis();
                System.out.println("10 seconds gone! size is:"+hs.size());
            }
        }
        System.out.println("Done"); 
    }
}

`