Boolean.hashCode()


122

hashCode()クラスBoolean のメソッドは、次のように実装されています。

public int hashCode() {
    return value ? 1231 : 1237;
}

なぜ1231と1237を使用するのですか?なぜ他にないのですか?


1
これら2つの数値は、十分に大きな素数です。詳細については、Wikipediaのハッシュテーブルに関する記事を参照してください。
BorisPavlović

回答:


140

1231と1237は、2つ(十分に大きい)の任意の素数です。他の2つの大きな素数は問題ありません。

なぜ素数なのか?
たとえば、1000と2000のように、複合数(素数ではない)を選択したとします。ブール値をハッシュテーブルに挿入すると、truefalseがバケット1000 % Nレスポンス2000 % N(バケットN数)に入ります。

今気づく

  • 1000 % 8 同じバケツ 2000 % 8
  • 1000 % 10 同じバケツ 2000 % 10
  • 1000 % 20 同じバケツ 2000 % 20
  • ....

つまり、多くの衝突が発生します。

これは、1000(2 3、5 3)2000の分解(2 4、5 3)非常に多くの共通要素を有しています。したがって、バケットサイズに共通の要素がある可能性は低いため、素数が選択されます。

なぜ大きな素数なのか。2と3はしませんか?
複合オブジェクトのハッシュコードを計算する場合、コンポーネントのハッシュコードを追加するのが一般的です。バケット数が多いハッシュセットで小さすぎる値を使用すると、オブジェクトの分布が不均一になる可能性があります。

衝突は重要ですか?ブールはとにかく2つの異なる値を持っていますか?
マップには、他のオブジェクトと共にブール値を含めることができます。また、Drunixで指摘されているように、複合オブジェクトのハッシュ関数を作成する一般的な方法は、サブコンポーネントのハッシュコード実装を再利用することです。この場合、大きな素数を返すのが適切です。

関連する質問:


1
これらは十分に大きいと思います。1より大きいgcdを取得するには、少なくとも2*1231 = 2462バケットが必要です。このような状況で衝突は問題になりますか?
aioobe

2
何がintに収まるかを考えると、実際には「かなり大きい」わけではないことは興味深いです。これらは、JDK Hashtableで適切に機能するのに十分な大きさですが、計算コストを最小限に抑えるのに十分小さいと思います。
ティロ

2
はい、あまり大きくないの印象的でし。しかし、素数が大きいほどコストが高くなると思いますか?
aioobe

3
@チロでは、衝突する前に1231 * 1237の倍数= 1,522,747バケットが必要です。これは十分な大きさです
ラチェットフリーク

2
バケット数との衝突を引き起こすことは、実際にはブール値の問題ではありませんが、複合オブジェクトのハズコードを取得する方法の一般的な構成、つまり、コンポーネントのハッシュコードに定数を乗算し、それらを加算することによります。
Drunix 2014年

2

上記のすべてに加えて、開発者からの小さなイースターエッグにもなります。

true:1231 => 1 + 2 + 3 + 1 = 7

7-ヨーロッパの伝統における幸運な数字です。

false:1237 => 1 + 2 + 3 + 7 = 13

13(別名、悪魔のダース)-不運な数。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.