LinkedHashMapはなぜ defaultにすべきではないか
まず、手のひらを返すようではあるが「走査順序が決定的」なのはそんなに悪くないと思う。プラットフォームや実行タイミングによらず、同じコードが同じふるまいをするのは望ましい。デバッグする時に余計な手間を減らせる。
しかし決定的にするために「なにも考えずに LinkedHashMapにすればよくね?」という態度が納得行かない。Blogでも "always" っていってるからそういう雰囲気を感じる。
そもそも Mapの実装は {Linked,}HashMapだけではない。TreeMapもある。EnumMapとかも好きなんだが、あまり使いでがないのが残念だ。いずれにしても、いろいろあるのに Map = LinkedHashMapだと考えてしまうと、いろいろあり得た最適化が適用できない。おまけに Mapの実装を知らずに追加順に依存したコードとか書きそうになる。
「追加順に依存する」というのは「走査順序の決定性に依存する」よりもっと強い依存だ。EnumMapだって TreeMapだって走査順序は決定的だ。でも追加順に走査されるわけじゃない。
でも Map = LinkedHashMap だと思いこんで、追加順に依存したコードが増えそうだ。せっかく Javaは Mapという抽象化を提供してくれたのに悲しい。
そもそも、最初の Blogの例で言えばそんなに順序に依存したコードを書いてるのがいけないんじゃない?
HashMap’s non-deterministic iteration order is to blame.
じゃねえよ。そんな割り算の順番に依存するコード書いてるのがいけないんだ。
Rubyの Hash
あと、感じたのがそもそも Rubyは "Hash” であり Javaは "Map" である。そこらへんに、仕様じゃなくて実装に基づく名前をつけちゃうのはどうよ、って思ったりもしたが Perlから引きずったんだろうし、そこらへん厳密にやらずにとりあえず作っていこうぜ、っていう script languageという性格からしたらありなんだろう。そこらへんのいい意味でのいい加減さが Rubyの Hashに順序を導入しちゃう決定に繋がったんだろうな、と夢想してる。
ちなみに Goは ”Map"であり、そこらへんがかえって走査順序に変な仮定を入れちゃいけない、ってお硬い判断に繋がったのかなあ。実装をかえられるかよくわからないけど。