Help us understand the problem. What is going on with this article?

Java Collection の操作方法の引き出しを増やそう①

More than 3 years have passed since last update.

Java でプログラムを書いていると,標準の java.util.Collection フレームワークを使うことが必須になるでしょうが,なるべくスマートに書こうよ,という趣旨.
第1弾として「初期化」と「変更不可能」について.それ以外は思い立ったら書きます.
Java 1.8, それと Guava, Apache Commons utils が使えるという状況を前提とします.

初期化

ナントカの一つ覚えのように Lists.newArrayList() ばかり呼ばないこと.

標準のコンストラクタ

標準のコンストラクタ.ダイアモンド演算子を書かなければいけない (1.6 以前なら総称型の省略も不可能),初期化のパターンとしてやや乏しいので,余り使わない.

List<String> lines = new ArrayList<>();
List<String> another = new ArrayList<>(lines); // java.util.Colleciton を引数で受けられる

Guava の初期化

コレクションの実装毎に、初期データを突っ込みつつインスタンス構築する方法を何パターンか用意してくれているので,使いやすい。
実装毎に初期化メソッドがたくさんあるので,API ドキュメントを読んだことない人はぜひご一読を.

List<String> lines = Lists.newArrayList("石井琢朗", "波留敏夫", "鈴木尚典");

Guava の Immutable Collection

変更不可能なコレクションを作る.

List<String> twoPlans = ImmutableList.of("佐伯貴弘", "中根仁");
twoPlans.add("マラベ") // UnsupportedOperationException が投げられる

// Key-Value を繰り返す
Map<Integer, String> rotation = ImmutableMap.of(11, "斎藤隆", 16, "川村丈夫", 21, "野村弘樹", 18, "三浦大輔", 63, "戸叶尚");

Immutable Collection の Builder

上記の Immutable Collections には,それぞれ Builder がある。

Builder<String> builder = ImmutableList.builder();
builder.add("島田直也");
builder.add("阿波野秀幸", "五十嵐英樹", "横山道哉"); // 可変長引数で承けられる。
List<String> releivers = builder.build();

java.util.Collections の singleton

要素を変更出来ないようにする場合,Immutable Collection の他にも,単一要素しか持たないなら,これで初期化するのもあり。

List<String> bobby = Collections.singletonList("ローズ");
Map<Integer, String> basesLoaded = Collections.singletonMap(Integer.valueOf(10), "駒田徳広");

変更不可能

初期化とも被る範囲もあるが,コレクションの状態を変更させない (add/remove などを許容しない) ようにすると,余計なことに気を使わなくて良くなるので,その方法について.
特に public Set<String> getXXX() みたいなメソッドの返す Collection は,変更不可能にしておいたほうが良いことが多い.(あくまで一般論)

java.util.Collections の unmodifiable

状態変更系のメソッドを呼ぶと UnsupportedOperationException を投げるようにしてあるラッパー.Effective Java にも書いてあるが,あまり良くないケースもある.オリジナルのコレクションが変更されないことがわかっている,もしくは一時的に返す View である場合にのみ使う.

Collection<String> coaches = Lists.newArrayList("権藤博", "山下大輔", "高木由一");

Collection<String> view = Collections.unmodifiableCollection(coaches);

view.add("森祇晶"); // 状態を変更するメソッドなので,これは UnsupportedOperationException() がスローされる。

coaches.add("牛島和彦"); // これは出来る。

view.contains("牛島和彦"); // 変更しないメソッドについては,view は coaches に処理を移譲するだけなので,true が返ってくる.

Guava の Immutable Collection

こっちは,元のコレクションの要素を新しいコレクションにも詰めるようにしているので,その心配なし。
少し余談になるが,copyOf というメソッド名は,「オリジナルのコピーを作ることでインスタンスを初期化するんだよ」ということを表している良いメソッド名であり,Static Factory Method のメリットを享受している良い例であると言える.(Effective Java の項目1を参照)

Collection<String> coaches = Lists.newArrayList("権藤博", "山下大輔", "高木由一");

// ラッパーではないので java.util.Collections の問題が起きない。
// コピーであることを示す、という意味で Static Factory Method のメリットも享受している。()
Collection<String> view = ImmutableList.copyOf(coaches);

「上記にはないけど,こんな書き方,よくしない?」というのあったら,ご指摘ください.

Mura-Mi
Application Engineer / Financial Engineer in Tokyo.
caddi
製造業の受発注プラットフォーム「CADDi」を提供しています。 モノづくりに携わるすべての人が、本来持っている力を最大限に発揮できる社会を実現する。産業の常識を変える「新たな仕組み」をつくります。 「CADDi」は金属加工品のCAD・設計図の解析から複雑な物流を表現するUIまで幅広い開発をしており、常に開発環境に最新の技術をとり入れて、より良いプロダクトを作るように心がけております。
https://corp.caddi.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away