流れるようなインタフェース - Collection 編

id:aufheben:20090215 で書いた「XXXUtils の乱用をやめる」の続編です。
Collection 関連の API も List、Map などのインタフェースと Collections ユーティリティクラスに分散しています。
たとえば、ある List をソートして、バイナリサーチで要素を見つけようとすると、以下のようなコードになります。

List<Integer> list;
...
Collections.sort(list);
int index = Collections.binarySearch(list, 256);

これを、流れるようなインタフェースを採用したライブラリで書き換えると、以下のようになります。

ListAdapter<Integer> list;
...
int index = list.sort().binarySearch(256);

次は、Map の初期化です。索引等で使用する不変な Map を初期化するコードを書いてみます。

Map<String, Integer> map = new LinkedHashMap<String, Integer>();
map.put("b", 1);
map.put("a", 2);
map.put("c", 3);
...
map = Collections.unmodifiableMap(map);

同じく、流れるようなインタフェースを採用したライブラリで書き換えると、こんな感じになります。

Map<String, Integer> map = new MapAdapter<String, Integer>()
    .put("b", 1)
    .put("a", 2)
    .put("c", 3)
    ...
    .unmodifiableMap();

お好みで、こんな風に書いてもいいかもしれません。

Map<String, Integer> map = new MapAdapter<String, Integer>() {{
    put("b", 1).put("a", 2).put("c", 3)...;
}}.unmodifiableMap();

Calendar のときと比べると、それほど有難みはありませんが、でも多少コードが書きやすく簡潔になります。
このようなライブラリを書いていて一番迷ったのは、オブジェクトを不変 (immutable) にするかどうかという点。不変にした方が間違いは少なそうですが、メソッドが呼ばれるたびに小さなオブジェクトが大量に生成されてしまうので、ひとまず同じインスタンスを使いまわす仕様にしています。最初はクラス名を XXXBuilder にしようかと思ったのですが、参照系のメソッドも持っていて、そのままで List や Map と同じようにも使えてしまうので、XXXAdapter という名前にしています。