hashtableのn * 2 + 1の意義

勉強になりました。
9
くまぎ @kumagi

【教えて】Javaのハッシュテーブルについて「新しいテーブルサイズは (古いサイズ * 2 + 1) になる。これは検索効率を低下させないための工夫である」という記述を見かけましたが、(古いサイズ * 2)ではなくそこに1足す事で具体的にどんな利益があるんですか?

2011-02-27 11:12:56
mzp @mzp

@kumagi 古いサイズが0になるときとか? 今思いついただけですけど

2011-02-27 11:14:15
くまぎ @kumagi

@mzp サイズ0のハッシュテーブルは作らないと思いますし、2のべき乗以外のサイズのテーブルになると&じゃなくて%で目的に至る必要があるので計算負荷がかかります。悪いこと尽くめだと思うのですが。

2011-02-27 11:25:05
tomo🐧@learning @cocoatomo

@kumagi @finalfusion サイズが 0 だったときのための安全策です.

2011-02-27 11:26:28
くまぎ @kumagi

@cocoatomo @finalfusion JavaのHashtableは初期サイズ0なのでしょうか。

2011-02-27 11:28:16
tomo🐧@learning @cocoatomo

@kumagi @finalfusion いいえ, 違います. 初期容量は 11 らしいです. しかし, 初期容量を指定できるコンストラクタがあるのでサイズ 0 のものを作ることは可能です. http://t.co/W8P5D9x

2011-02-27 11:33:09
くまぎ @kumagi

@cocoatomo @finalfusion サイズ0のテーブルに要素つっこんだら例外投げるか、強制的にサイズ1にするかぐらいしてもいいんじゃないかと思います。初期容量11は真剣に謎ですね…。

2011-02-27 11:36:33
tomo🐧@learning @cocoatomo

@kumagi @finalfusion (oldSize * 2 + 1) という式で, サイズが 0 だったら 1 にしてますが. そういうことではなく? 初期サイズは謎です. ちなみに ArrayList の初期サイズは 10 です. 謎です.

2011-02-27 11:38:37
くまぎ @kumagi

@cocoatomo @finalfusion サイズが0の時だけifで切って1にする、もしくはテーブルサイズが0なんて例外中の例外は特別扱いしていいんじゃないか、ってことです。

2011-02-27 11:43:58
tomo🐧@learning @cocoatomo

@kumagi @finalfusion う〜ん, 理由は分からないですねぇ. JVM 上では if のコストってそんなに高いんでしょうかねぇ……

2011-02-27 11:47:09
_sss_ @_sss_

@kumagi 少しだけ java.uti.Hashtable のソースを見てみたのですが "newCapacity the new capacity, MUST be a power of two" と書いてあるくらいなので、その +1 というのが間違ってるのかな、と。

2011-02-27 11:28:47
くまぎ @kumagi

@_sss_ ですよね。わざわざ足す意義が見つからないです。

2011-02-27 11:34:53
oza @oza_x86

@kumagi ほえー,ちなみにソースは?

2011-02-27 11:30:28
くまぎ @kumagi

@oza_x86 http://www.nurs.or.jp/~sug/soft/super/hash.htm の一番下です。dankogaiさんのブログでは「ここでは新しいハッシュテーブルの大きさは2倍+1要素としています。多くのハッシュテーブルの実装ではそうなっています」と。

2011-02-27 11:33:12
アノヒト(スマホ大破:連絡先ゼロ) @mindstack

@kumagi 初期サイズ0が許される。でも、デフォルトサイズも11というキリの悪い数字にされてるね。デフォルト負荷率75%も、どうしてそうなってるのかは知らない。

2011-02-27 11:33:18
くまぎ @kumagi

@mindstack 11という数字が謎過ぎる。 load factor 75%はopen addressingを意識してでしょうか… http://en.wikipedia.org/wiki/File:Hash_table_average_insertion_time.png

2011-02-27 11:38:47
アノヒト(スマホ大破:連絡先ゼロ) @mindstack

@kumagi loadfactorに100%も指定できるようだし、そこら辺の処理用に+1配列の冗長性使ってるんじゃないかと推測。

2011-02-27 11:41:46
くまぎ @kumagi

@mindstack なるほど、open addressingに対して100%使用は無限ループになりかねませんし。でもそれを「検索効率を低下させないための工夫」と呼ぶのかは疑わしいです。

2011-02-27 11:45:12
くまぎ @kumagi

そうか、ハッシュ関数が偏ったときにも性能がガタ落ちしないための工夫か。table[0]の物が3箇所にバランスされる。

2011-02-27 11:47:53
勇士Q @ucq

ハッシュテーブルのサイズの件はは以前どっかでみたような

2011-02-27 11:29:49
勇士Q @ucq

+1するのはなるべく素数にしたいから? Rubyのハッシュテーブルのサイズは素数になるように実装されてるっけ。

2011-02-27 11:39:08
Tsukasa #01 @a4lg

@ucq たしかにメルセンヌ数 (メルセンヌ素数ではない!) を 2n+1 すれば次のメルセンス数になるねぇ。それが素数になるかは別として。

2011-02-27 11:40:47