はじめに
どうも、稲葉です。この記事では、変更不可能なリストについてまとめます。
定義
変更不可能なリストとは、要素の追加や削除、置換、整列ができないリストです。List.copyOf
やList.of
、Collectors.toUnmodifiableList
で作成でき、add
やaddAll
、remove
、replaceAll
、set
、sort
を呼び出すと、UnsupportedOperationException
がスローされます。
// 変更不可能なリスト[A, B, C]を作成
final List<String> list12 = List.of("A", "B", "C");
// 要素を追加しようとすると、UnsupportedOperationExceptionが発生
list12.add("D");
list12.addAll(List.of("E"));
// 要素を削除しようとすると、UnsupportedOperationExceptionが発生
list12.remove("F");
// 要素を置換しようとすると、UnsupportedOperationExceptionが発生
list12.replaceAll(String::toLowerCase);
list12.set(0, "a");
// 要素を整列しようとすると、UnsupportedOperationExceptionが発生
list12.sort(Comparator.reverseOrder());
似て非なるもの
Arrays.asList
で作成したリストは、要素の追加と削除ができませんが、要素の置換と整列ができるため、変更不可能なリストではありません。
// Arrays.asListでリスト[a, b, c]を作成
final List<String> arrayList = Arrays.asList("a", "b", "c");
// 要素を置換し、[a, b, c]を[Z, X, Y]に変更
arrayList.set(0, "Z");
arrayList.set(1, "Y");
arrayList.set(2, "X");
// 要素を置換し、[Z, Y, X]を[z, y, x]に変更
arrayList.replaceAll(String::toLowerCase);
// 要素を整列し、[z, y, x]を[x, y, z]に変更
arrayList.sort(String::compareTo);
// リストをコンソールに表示
System.out.println(arrayList); // [x, y, z]
Collections.unmodifiableList
で作成したリストは、その引数を変更すると変更が反映されるため、変更不可能なリストではありません。変更不可能なビューといいます。
// 変更可能なリスト[foo]を作成
final List<String> arrayList = new ArrayList<>();
arrayList.add("foo");
// List.copyOfとCollections.unmodifiableListで変更不可能なリストとビューを作成
final List<String> list12 = List.copyOf(arrayList);
final List<String> unmodifiableList = Collections.unmodifiableList(arrayList);
// 引数のリスト[foo]を[bar]に変更
arrayList.set(0, "bar");
// 変更不可能なリストとビューをコンソールに表示
System.out.println(list12); // [foo]
System.out.println(unmodifiableList); // [bar]
気を付けること
List
インタフェースを実装しているため、変更不可能なリストはadd
やaddAll
、remove
、replaceAll
、set
、sort
を呼び出してもコンパイルができてしまいます。開発チームで使用方法を取り決めておかないと、テスト時・運用時にUnsupportedOperationException
が発生するかもしれません。
変更不可能なリストを変更可能なリストに変換する方法
ArrayList
やLinkedList
、Vector
のコンストラクタに変更不可能なリストをやると、変更可能なリストに変換できます。新規のインスタンスを作成するため、変更可能なリストを変更しても引数のリストは変更されません。
// 変更不可能なリスト[foo]を作成
final List<String> list12 = List.of("foo");
// ArrayListで変更可能なリストを作成
final List<String> arrayList = new ArrayList<>(list12);
// 変更可能なリスト[foo]を[bar]に変更
arrayList.set(0, "bar");
// List.ofとArrayListで作成したリストをコンソールに表示
System.out.println(list12); // [foo]
System.out.println(arrayList); // [bar]
おわりに
というわけで、この記事では変更不可能なリストについてあらましを書いてみました。詳細についてはJava Platformm, Standard Edition Core Libraries, Release 11を読んでください。