サブリスト(subList)の注意点(ビュー) — 変更の影響範囲
Java の List.subList(from, to) は「部分リスト」を返しますが、これは コピーではなく元リストのビュー(見え方) です。初心者がよくつまずくのは「サブリストを変更すると元リストも変わる」「元リストを変更するとサブリストが壊れる」点です。安全に使うための知識を整理します。
基本の仕組み
- ビュー:
subListは元リストの一部を「見せる」だけ。新しいリストを作っているわけではない。 - 範囲:
fromは開始インデックス(含む)、toは終了インデックス(含まない)。 - 双方向の影響:
- サブリストを変更すると元リストも変わる。
- 元リストを変更するとサブリストも影響を受ける。
- 構造変更の制約: 元リストに対してサブリストの範囲外で add/remove すると、サブリストは 不整合になり
ConcurrentModificationExceptionが出ることがある。
基本コード例
1. サブリストはビュー
import java.util.*;
public class SubListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("A", "B", "C", "D", "E"));
List<String> sub = list.subList(1, 4); // [B, C, D]
System.out.println("sub = " + sub);
sub.set(1, "X"); // sub[1] = "C" → "X"
System.out.println("list = " + list); // [A, B, X, D, E] (元リストも変わる)
}
}
Java2. 元リストを変更するとサブリストが壊れる
List<String> list = new ArrayList<>(List.of("A", "B", "C", "D", "E"));
List<String> sub = list.subList(1, 4); // [B, C, D]
list.add("F"); // 元リストに範囲外の変更
System.out.println(sub); // ここで ConcurrentModificationException が出る可能性
Javaよくある用途と注意点
- 部分削除: サブリストを
clear()すると、その範囲が元リストから削除される。list.subList(1, 3).clear(); // list の index 1〜2 を削除 - 部分コピーが欲しい:
new ArrayList<>(list.subList(...))とすれば独立したコピーになる。ビューではなく新しいリスト。 - 安全な利用: サブリストを使うときは「元リストに対して範囲外の構造変更をしない」ことが重要。
例題で練習
例題1: 部分削除
List<Integer> nums = new ArrayList<>(List.of(1,2,3,4,5,6));
nums.subList(2,5).clear(); // index 2〜4 を削除
System.out.println(nums); // [1, 2, 6]
Java例題2: 部分コピーで安全に利用
List<String> list = new ArrayList<>(List.of("A","B","C","D","E"));
List<String> copy = new ArrayList<>(list.subList(1,4)); // 独立コピー
list.add("F"); // 元リスト変更しても copy は安全
System.out.println(copy); // [B, C, D]
Java例題3: サブリストをソート
List<String> list = new ArrayList<>(List.of("E","D","C","B","A"));
List<String> sub = list.subList(1,4); // [D,C,B]
sub.sort(Comparator.naturalOrder());
System.out.println(list); // [E, B, C, D, A] (元リストも変わる)
Javaテンプレート集
- 部分ビュー取得
List<T> sub = list.subList(fromIndex, toIndex);
Java- 部分削除
list.subList(from, to).clear();
Java- 部分コピー(安全)
List<T> copy = new ArrayList<>(list.subList(from, to));
Java- 部分ソート
list.subList(from, to).sort(comparator);
Java実務でのコツ
- ビューかコピーかを意識する: サブリストはビュー。独立したリストが欲しいならコピーを作る。
- 元リストの構造変更に注意: サブリスト利用中は元リストに add/remove しない。
- 範囲操作に便利: 部分削除や部分ソートはサブリストで簡潔に書ける。
- 例外に備える: サブリストを保持したまま元リストを操作すると
ConcurrentModificationExceptionが出ることがあるので、設計で避ける。
まとめ
subListは ビューであり、元リストと内容を共有する。- サブリストの変更は元リストに反映され、逆も影響する。
- 元リストの範囲外変更はサブリストを壊すので注意。
- 独立した部分リストが欲しいなら
new ArrayList<>(subList(...))でコピーを作る。
👉 練習課題として「リストの中間部分を subList で取り出してソートし、元リストに反映させる」プログラムを書いてみると、ビューの性質がよく理解できます。
