hashcodeを書き直した理由となぜ31の個人で理解したのか
4320 ワード
まず自分の大部分の理解の出所を宣言します:どのようにhashCode()とequals()の方法を書き換えます次に自分の理解:1、まずjavaの中でset、HashMapはリストなどの下層の記憶を含むようで、記憶領域はnの部分に分けて、具体的にどの部分がhashcodeによって決定されたのか、つまりクエリーの時彼はhashcodeのすべての小さいクエリーの範囲を通じて、だから、すべてのhashcodeが同じであれば、あなたのhashcodeは定数を返します.その結果、格納された後、1つの領域に格納され、クエリーの時にチェーンクエリーになり、完全に効率的ではありません.2、hashcodeがランダム数を返しているか、hashcodeを書き直さないと、2つのオブジェクトが同じであっても問題が発生します.例(上のブログから適用):まず2つの新しいCoderオブジェクトを作成します.
hashCode()メソッドを書き換えずにCoderのequals()メソッドを書き換えたと仮定します.
次にHashSetを作成し、c 1オブジェクトをsetに入れます.
最後:
contains(c 2)法はtrueを返すことを期待するが,実際にはfalseを返す.
c 1とc 2のnameとageは同じですが、なぜ私はc 1をHashSetに入れた後、contains(c 2)を呼び出してfalseに戻ったのでしょうか.これがhashCode()です.hashCode()を書き換える方法がないので、HashSetはc 2を探すとき、異なるbucketの中で探します.例えばc 1は05というbucketの中に入っていますが、c 2を探すときに06というbucketの中で探しています.もちろん見つかりません.そのため、hashCode()を書き換える目的は、A.equals(B)がtrueを返す場合、A,BのhashCode()は同じ値を返す.
次にhashcodeを書き直すときに31という数で書くのが一般的です.
まずhashcodeを生成することをできるだけ一意に保つために、必ず1つの素数を係数(ここの31)として使用しますが、なぜ他の素数ではなく31なのか、31はi*31==(i<<5)-1で表すことができ、現在多くの仮想マシンでは関連最適化が行われていますが、31を使用する理由はhashアドレスをよりよく割り当てるためかもしれません.そして31は5 bitしか占めていません!したがって、効率的には2の5回のマイナス1であり、コンピュータにとって2の乗算除算操作は変位操作を行うだけであり、例えば*32は左シフト5ビットである.つまり、31はコンピュータの観点から言えば、演算が速く、メモリの切断が少なく、仮想マシンが最適化されているのが慣例です.したがって、31を係数としてhashcode以上の理解は、hashcodeに31係数が用いられている問題に関する理解に由来する.
Coder c1 = new Coder("bruce", 10);
02. Coder c2 = new Coder("bruce", 10);
hashCode()メソッドを書き換えずにCoderのequals()メソッドを書き換えたと仮定します.
@Override
02. public boolean equals(Object other) {
03. System.out.println("equals method invoked!");
04.
05. if(other == this)
06. return true;
07. if(!(other instanceof Coder))
08. return false;
09.
10. Coder o = (Coder)other;
11. return o.name.equals(name) && o.age == age;
12. }
次にHashSetを作成し、c 1オブジェクトをsetに入れます.
Set set = new HashSet();
set.add(c1);
最後:
System.out.println(set.contains(c2));
contains(c 2)法はtrueを返すことを期待するが,実際にはfalseを返す.
c 1とc 2のnameとageは同じですが、なぜ私はc 1をHashSetに入れた後、contains(c 2)を呼び出してfalseに戻ったのでしょうか.これがhashCode()です.hashCode()を書き換える方法がないので、HashSetはc 2を探すとき、異なるbucketの中で探します.例えばc 1は05というbucketの中に入っていますが、c 2を探すときに06というbucketの中で探しています.もちろん見つかりません.そのため、hashCode()を書き換える目的は、A.equals(B)がtrueを返す場合、A,BのhashCode()は同じ値を返す.
次にhashcodeを書き直すときに31という数で書くのが一般的です.
@Override
02. public int hashCode() {
03. int result = 17;
04. result = result * 31 + name.hashCode();
05. result = result * 31 + age;
06.
07. return result;
08. }
まずhashcodeを生成することをできるだけ一意に保つために、必ず1つの素数を係数(ここの31)として使用しますが、なぜ他の素数ではなく31なのか、31はi*31==(i<<5)-1で表すことができ、現在多くの仮想マシンでは関連最適化が行われていますが、31を使用する理由はhashアドレスをよりよく割り当てるためかもしれません.そして31は5 bitしか占めていません!したがって、効率的には2の5回のマイナス1であり、コンピュータにとって2の乗算除算操作は変位操作を行うだけであり、例えば*32は左シフト5ビットである.つまり、31はコンピュータの観点から言えば、演算が速く、メモリの切断が少なく、仮想マシンが最適化されているのが慣例です.したがって、31を係数としてhashcode以上の理解は、hashcodeに31係数が用いられている問題に関する理解に由来する.