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