Java : List の初期化方法いろいろ
本記事では、List の初期値を設定する方法を5つご紹介します。
その中で、インスタンスイニシャライザはあまりおすすめしない理由も補足します。
リストの初期化
簡単なまとめ
初期化方法 | おすすめ度 | 不変オブジェクト | サイズの変わる操作 |
---|---|---|---|
List.of | ☆☆☆ | 〇 | × |
Arrays.asList | ☆☆ | × | × |
リストのコンストラクタ | ☆☆ | × | 〇 |
Collections.addAll | ☆☆ | × | 〇 |
インスタンスイニシャライザ | ☆ | × | 〇 |
関連 : 不変オブジェクト(イミュータブル) とは
コード例
初期化方法 | コード例 |
---|---|
List.of |
|
Arrays.asList |
|
リストのコンストラクタ |
|
Collections.addAll |
|
インスタンスイニシャライザ |
|
List.of
もし List に対して変更が必要なければ、List.of メソッドを使うのがおすすめです。
List.of メソッドは、不変オブジェクト である List を作成します。
final List<String> list = List.of("aaa", "bbb", "ccc");
System.out.println(list); // [aaa, bbb, ccc]
作成した List は不変オブジェクトです。
そのため、List を変更しようとすると
- 非チェック例外 : UnsupportedOperationException
が発生します。
List の要素を変更する set メソッドを使う例です。
final List<String> list = List.of("aaa", "bbb", "ccc");
System.out.println(list); // [aaa, bbb, ccc]
list.set(1, "XXX"); // UnsupportedOperationException 発生
Arrays.asList
Arrays クラスの asList メソッドを使う例です。
final List<String> list = Arrays.asList("aaa", "bbb", "ccc");
System.out.println(list); // [aaa, bbb, ccc]
List.of メソッドに似ていますが、要素の変更は OK です。
final List<String> list = Arrays.asList("aaa", "bbb", "ccc");
System.out.println(list); // [aaa, bbb, ccc]
// 要素の変更はOK
list.set(1, "XXX");
System.out.println(list); // [aaa, XXX, ccc]
ただし、リストのサイズが変わる操作 (追加や削除など) はできません。
final List<String> list = Arrays.asList("aaa", "bbb", "ccc");
System.out.println(list); // [aaa, bbb, ccc]
// リストのサイズが変わる操作はNG
list.add("YYY"); // UnsupportedOperationException 発生
リストのコンストラクタ
ArrayList クラスは List インタフェースの実装の1つです。
コンストラクタに Collection を指定すことで要素を初期化できます。
(ちなみに List は Collection のサブインタフェースです)
少し冗長かもしれませんが、ArrayList のコンストラクタと
- List.of メソッド
- Arrays.asList メソッド
を組み合わせて List を初期化できます。
もちろん、ArrayList なのでリストの変更 (追加・削除) が可能です。
【 List.of を使った例 】
final List<String> list = new ArrayList<>(List.of("aaa", "bbb", "ccc"));
System.out.println(list); // [aaa, bbb, ccc]
list.add("XXX");
System.out.println(list); // [aaa, bbb, ccc, XXX]
※今回は ArrayList を使いましたが、他の実装 … 例えば LinkedList を使っても OK です。
Collections.addAll
もし1行の初期化にこだわらないのであれば、Collections.addAll メソッドが使えます。
final List<String> list = new ArrayList<>();
Collections.addAll(list, "aaa", "bbb", "ccc");
System.out.println(list); // [aaa, bbb, ccc]
もちろん、ArrayList なのでリストの変更 (追加・削除) が可能です。
final List<String> list = new ArrayList<>();
Collections.addAll(list, "aaa", "bbb", "ccc");
System.out.println(list); // [aaa, bbb, ccc]
list.add("XXX");
System.out.println(list); // [aaa, bbb, ccc, XXX]
インスタンスイニシャライザ
インスタンスイニシャライザを使った初期化も可能です。
具体的な例で見てみましょう。
final List<String> list = new ArrayList<>() {
{
add("aaa");
add("bbb");
add("ccc");
}
};
System.out.println(list); // [aaa, bbb, ccc]
これは、分解すると2つの構造に分けられます。
最初の { ... } は匿名クラス(Anonymous Class) の宣言です。
final List<String> list = new ArrayList<>() {
... 匿名クラスの宣言 ...
};
そして、その中の { ... } がインスタンスイニシャライザです。
final List<String> list = new ArrayList<>() {
{
... インスタンスイニシャライザ ...
}
};
インスタンスイニシャライザはさておき、匿名クラスには注意点があります。
- 匿名クラスは、内部クラスの1つです。そのため、外側のクラス参照を暗黙的に保持します。
- これはガベージ・コレクタによるメモリ解放を阻害するおそれがあります。
- AraryList は serialVersionUID を定義していますが、その匿名クラスは serialVersionUID を定義していません。
- シリアライズするときは特に注意が必要です。
- 静的解析ツール (lint など) で「serialVersionUID を定義していませんよ」と警告されることがあります。
- 外側のクラス参照を持つので、意図せず外側のクラスまでシリアライズしてしまうリスクがあります。
もし使うのであれば、匿名クラスとインスタンスイニシャライザをよく理解してから使うことをおすすめします。
参考 : [Java] 匿名クラスとインスタンスイニシャライザを使って初期化したデータのシリアライズに失敗した話
まとめ
本記事では、List の初期化方法を5つご紹介しました。
- 不変オブジェクトなら … List.of メソッド
- 可変オブジェクトなら … リストのコンストラクタ or Collections.addAll メソッド
を使うのがおすすめです。
関連記事
- List(リスト)の基本
- Map(マップ)の基本
- Set(セット)の基本
- Map の初期化方法いろいろ
- Set の初期化方法いろいろ
- 配列 vs. List
- 配列からListへの変換
- List から配列への変換
- API 使用例
- Collection (コレクション)
- Collections (コレクション操作)
- Comparable
- Comparator
- Iterator
- List (リスト)
- Map (マップ)
- Map.Entry (キーと値のペア)
- Queue (キュー)
- AbstractQueue
- ArrayBlockingQueue (ブロッキング・配列キュー)
- ArrayDeque (両端キュー)
- BlockingDeque (ブロッキング・両端キュー)
- BlockingQueue (ブロッキング・キュー)
- ConcurrentLinkedDeque (並列処理用・両端キュー)
- ConcurrentLinkedQueue (並列処理用キュー)
- Deque (両端キュー)
- LinkedBlockingDeque (ブロッキング・リンク両端キュー)
- LinkedBlockingQueue (ブロッキング・リンクキュー)
- LinkedList (二重リンク・リスト)
- PriorityBlockingQueue (ブロッキング・優先度付きキュー)
- PriorityQueue (優先度付きキュー)
- RandomAccess
- Set (セット)
- Spliterator