web-dev-qa-db-ja.com

同じハッシュコードを持つ2つの等しくないオブジェクト

Hashcode()とequals()の概念は

1)equal()に従って2つのオブジェクトが等しい場合、これらの2つのオブジェクトのそれぞれでハッシュコードメソッドを呼び出すと、同じハッシュコードが生成されます。

そして他のものは

2)equal()によって2つのオブジェクトが等しくない場合、2つのオブジェクトのそれぞれでハッシュコードメソッドを呼び出すと、異なる値が生成される必要はありません。

私は最初に試して理解しましたが、これは最初のポイントのコードです。

public class Test {
    public static void main(String[] args) {

        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        map.put(1, 11);
        map.put(4, 11);
        System.out.println(map.hashCode());
        Map<Integer, Integer> map1 = new HashMap<Integer, Integer>();
        map1.put(1, 11);
        map1.put(4, 11);
        System.out.println(map1.hashCode());
        if (map.equals(map1)) {
            System.out.println("equal ");
        }
    }
}

上記のプログラムは、2つの異なるオブジェクトに同じハッシュコードを与えます。

誰かが例で私を説明できますか?equals()に従って等しくない2つの異なるオブジェクトが同じハッシュコードをどのように持つことができますか?.

15
Saha

2)必須ではありませんです。2つのオブジェクトがequal()に従って不等の場合、2つのオブジェクトのそれぞれでハッシュコードメソッドを呼び出すと、異なる値が生成される必要があります。

ハッシュ関数に応じて、2つの異なるオブジェクトが同じハッシュコードを持つことができます。ただし、同じである2つのオブジェクトは、ハッシュされたときに同じ結果を生成する必要があります(誰かが乱数を使用してハッシュ関数を実装した場合を除き、その場合は役に立ちません)。

たとえば、整数をハッシュしていて、ハッシュ関数が(n % 10)次に番号17および番号27も同じ結果になります。これは、それらの数値が同じであることを意味するものではありません。

26
Jonathan

文字列の例(以下のすべての文字列のハッシュコードは0です):

public static void main(String[] args) {
    List<String> list = Arrays.asList("pollinating sandboxes",
                                      "amusement & hemophilias",
                                      "schoolworks = perversive",
                                      "electrolysissweeteners.net",
                                      "constitutionalunstableness.net",
                                      "grinnerslaphappier.org",
                                      "BLEACHINGFEMININELY.NET",
                                      "WWW.BUMRACEGOERS.ORG",
                                      "WWW.RACCOONPRUDENTIALS.NET",
                                      "Microcomputers: the unredeemed Lollipop...",
                                      "Incentively, my dear, I don't tessellate a derangement.",
                                      "A person who never yodelled an apology, never preened vocalizing transsexuals.");
    for (String s : list) {
        System.out.println(s.hashCode());
    }
}

この投稿 から盗まれた)。

8
assylias

hashCode()には32ビットの可能な値があります。オブジェクトにはこれよりもはるかに多くのオブジェクトが含まれる可能性があるため、同じhashCodeを持つオブジェクトがいくつかあることになります。つまり、オブジェクトが一意であることを保証できません。

これは、サイズが制限されたハッシュコレクションではさらに悪化します。 HashMapの最大容量は1 << 30または約10億です。つまり、実際に使用されるのは30ビットのみであり、コレクションで16 GB以上を使用せず、1,000バケット(または技術的には1 << 10)である場合は、実際には1000バケットしかありません。

注:HotSpot JVMでは、デフォルトのObject.hashCode()が負になることはなく、31ビットしかありませんが、理由はわかりません。

同じhashCodeで多くのオブジェクトを生成したい場合は、Longを見てください。

// from Long
public int hashCode() {
    return (int)(value ^ (value >>> 32));
}

for(long i = Integer.MIN_VALUE; i < Integer.MAX_VALUE;i++) {
    Long l = (i << 32) + i;
    System.out.print(l.hashCode()+" ");
    if (i % 100 == 0)
        System.out.println();
}

これにより、hashCodeが0の40億のLongが生成されます。

6
Peter Lawrey

HashMapの実装方法とその目的がわかっているとしたら、理解するのは簡単ではありません。ハッシュマップは、大きな値のセットを受け取り、それらを非常に小さなセット(バケット)に分割して、要素をより高速に取得します。基本的には、要素の完全なリストではなく、1つのバケットを検索するだけで済みます。バケットは、インデックスがハッシュコードである配列にあります。各バケットには、同じハッシュコードを持つ要素のリンクリストが含まれていますが、equal()ではありません。 Java 8)では、バケットサイズが大きくなると、ツリーマップを使用するようになったと思います。

2
Steven Rock

hashCodeの目的は、次の公理と結果を可能にすることです。

  • たまたま2つのオブジェクトのハッシュコードを知っていて、それらのハッシュコードが一致しない場合、オブジェクトをさらに調べて、オブジェクトが一致しないことを知る必要はありません。任意に選択された2つの一致しないオブジェクトが一致するハッシュコードを持つ可能性が10%であっても、ハッシュコードをテストすると、そうでなければ必要な比較の90%を排除できます。 99.99%を排除するほど大きな勝利ではありませんが、それでも間違いなく価値があります。

  • バンチ内のどのオブジェクトにも特定のハッシュコードがないことは、そのバンチ内のどのオブジェクトもそのハッシュコードとオブジェクトを照合しないことを意味します。オブジェクトのコレクションをハッシュコードが偶数であるオブジェクトと奇数であるオブジェクトに分割し、ハッシュコードが偶数である特定のアイテムがあるかどうかを確認したい場合、何も調べる必要はありません。奇数ハッシュアイテムのコレクション。同様に、偶数ハッシュコレクションで奇数ハッシュアイテムを探す必要もありません。したがって、2つの値のハッシュでさえ検索をほぼ半分に高速化できます。コレクションを小さなパーティションに分割すると、物事をさらに高速化できます。

hashCode()は、すべてのアイテムが異なるハッシュを返す場合に最大のメリットを提供しますが、多くのアイテムが同じハッシュ値を持つ場合でも大きなメリットを提供できることに注意してください。 90%の節約と99.99%の節約の違いは、数値が示唆するよりもはるかに大きいことが多いため、合理的に容易に99%、99.9%、またはそれ以上の改善を行うことができれば、ゼロの誤一致があり、コレクションにいくつかの誤一致があることはごくわずかです。

1
supercat

実際にはとても簡単です。

最初に、ハッシュコードが何であるかを知る必要があります。

Javaでは、ハッシュコードは単純に32ビットの符号付き整数で、問題のデータから何らかの方法で導出されます。整数型は通常、(Int Data)Mod(妥当な大きな素数)だけです。

整数に対して単純なハッシュを実行してみましょう。
定義:

public int hash(int num){ return num % 19 ; } 

この場合、19と38はどちらもハッシュ値0を返します。

文字列型の場合、ハッシュは個々の文字と文字列内の各文字の位置から導出され、かなり大きな数で除算されます。 (または、Javaの場合、32ビットの合計でのオーバーフローを無視します)。

可能な文字列がいくつでもあり、文字列のハッシュコードの数が限られている(2 ^ 32)とすると、鳩の穴の原理では、同じハッシュコードを生成する少なくとも2つの異なる文字列があると述べています。

0
Chris Cudmore

実際、このリンクはハッシュコードがより明確に等しい場合にどうなるかを説明しています。

http://www.javamadesoeasy.com/2015/02/hashmap-custom-implementation.html

0
madhu_karnati

理解に役立つと思います...

Javaオブジェクトのハッシュコードは単なる数値であり、32ビットの符号付き整数であり、オブジェクトをハッシュベースのデータ構造で管理できるようにします。ハッシュコードはJVMによってオブジェクトに割り当てられた一意のID番号。ただし、実際には、ハッシュコードはオブジェクトの一意の番号ではありません。2つのオブジェクトが等しい場合、これらの2つのオブジェクトは同じハッシュコードを返す必要があります。したがって、hashcode()メソッドを実装する必要があります2つのオブジェクトが等しい場合、つまりそのクラスのequal()メソッドで比較される場合、これらの2つのオブジェクトは同じハッシュコードを返す必要があるクラス。hashCodeをオーバーライドする場合は、equalsメソッドもオーバーライドする必要があります。

ref: https://www.Java2novice.com/Java_interview_questions/hashcode/

0
Vladimir Yel