Java SE9からList.of()メソッドが登場しました。
気になるのでまとめたいと思います。
List.of()メソッドとは
List.of()メソッドは簡単に変更が不可能(unmodifiable)なリストを作成することができます。
List.of()にはわかりやすく2つの特徴があります。(他にもあるようですが飛ばします。)
- nullは許容しない
- unmodifiable(変更不可)である(追加・削除・置換はできない)
- リスト内の要素の順序は、引数の順序、または指定された配列内の要素の順序と同じです(並び替え不可)
- value-basedである
List.of()を使ってみる!
List.of()メソッドは引数なしの形から1-10個までの引数、と可変長引数の12個があります。全部紹介するのも長ったらしいのでList.of()がどんなものかサンプルコードを交えて紹介していきます。
※ import java.util.*; で実験しています。
List.of() 引数なしのサンプルコード
nullを許容しないList.of()ですが、「List.of()」はどんなリストを作成するのでしょうか。
// 0個の要素を含んだ不変のリストが作成されます。
List list = List.of();
System.out.print(list); // []
使い道がよくわかりませんが。コンパイルエラーや実行時エラーになることはありません。
List.of() 引数ありのサンプルコード
引数ありのList.of()を使ってみます。
// List.of()でリストを作成
List list = List.of(1,2,3);
System.out.print(list); // [1, 2, 3]
// ArrayList()との比較
List list = new ArrayList<>();
list.add(“Hello”);
list.add(“Program”);
list.add(“Life”);
System.out.print(list); // [Hello, Program, Life]
List.ofを使えば瞬時にListへ値を挿入できます。
List.of() 引数に変数のサンプルコード
変数をいれてみます。
Integer[] array1 = {1,2,3};
List list = List.of(array1);
System.out.println(list); // [1, 2, 3]
並び順は変数と同じで固定されます。
List.of()異なる型のサンプルコード
異なる型を引数に入れるとどうなるでしょう。
List list = List.of(1,”Hello”,3.5, ‘a’);
System.out.print(list); // [1, Hello, 3.5, a]
混在することが可能です。
不変であるの検証
List arrayList1 = List.of(1,2,3);
arrayList1.add(4); // java.lang.UnsupportedOperationException
// おまけ
List arrayList2 = new ArrayList(List.of(1,2,3));
arrayList2.add(4);
System.out.println(arrayList2); //[1, 2, 3, 4]
List.of()はunmodifiable(変更不可)なのでadd()で値を追加しようとすると実行時エラーとなります。
おまけ:new ArrayList()内でList.of()をしてあげると変更可能です。初期値を設定する際にadd()で値を入れなくていいので便利です。
並べ替えはできない検証
並べ替えはできないようなので実験。
List<Integer> list = List.of(5,2,6,4,3,1);
Collections.sort(list); // UnsupportedOperationException
実行時エラーとなりました。
インスタンスの検証 (value-based)
List list1 = List.of(1,2,3);
List list2 = List.of(1,2,3);
System.out.println(list1 == list2); // false
System.out.println(list1.equals(list2)); // true
list1 = list2;
System.out.println(list1 == list2); // true
value-based聞いたことなかったですが、value-basedのものは、x.equals(y)で比較することで値が同等とみなされるようです。
Arrays.asList()との違い
上記のおさらいもかねて、よく比較しているのを見かけるのでついでに。
変更可能と不可
List.of()は変更不可(unmodifiable) のリストなので1度決めた値を変更することはできません。
Arrays.asList()は変更可能です。
サンプルコード
// Arrays.asList()の場合
List<String> list1 = Arrays.asList(“1″,”2”);
list1.set(0,”5″); // 変更可能
// List.of()の場合
List<String> list2 =List.of(“1″,”2”);
list2.set(0,”5″); // 実行時エラー (UnsupportedOperationException) 不変のため使えない
nullの許容
List.of()はnullを許容することはできませんが、Arrays.asList()はnullも許容します。
サンプルコード
// Arrays.asList()の場合
List list1= Arrays.asList(1, 2, null); // nullを許容
// List.of()の場合
List list2 = List.of(1, 2, null); // 実行時エラー (NullPointerException) nullを許容しない
contains(null)での違い
// Arrays.asList()の場合
List list1 = Arrays.asList(1, 2, 3);
System.out.println(list1.contains(null)); // false
// List.of()の場合
List list2 = List.of(1, 2, 3);
System.out.println(list2.contains(1)); // true
list2.contains(null); // 実行時エラー (NullPointerException)
値の参照
// Arrays.asList()の場合
Integer[] array = {1,2,3};
List list = Arrays.asList(array);
array[1] = 10; System.out.println(list); // [1, 10, 3] arrayと共通の値を参照
// List.of()の場合
Integer[] array = {1,2,3};
List list = List.of(array);
array[1] = 10;
System.out.println(list); // [1, 2, 3] arrayと異なる値を参照
おわり
List.of()を使うと予期せず値を変更されたりせずに便利そうですね。
List.of()以外にもSet.of()とかあってシリーズもなんですかね。今回は力尽きたので深追いしませんでしたが、どこかで調べたいと思います。
参考
Java 9 Factory Methods
What is the difference between List.of and Arrays.asList?
https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/util/List.html