この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:guest
更新日時:2026-06-11 07:29:05

タイトル: List
SEOタイトル: Java List インターフェース完全ガイド - ArrayList / LinkedList / List.of / immutable

この記事の要点
  • List は Java Collections の中核インターフェース。順序を保つ・重複を許すコレクション
  • 主要実装: ArrayList(既定)/ LinkedList(先頭末尾 O(1))/ Vector(古い、スレッドセーフ)/ CopyOnWriteArrayList(並行)
  • List.of(...) Java 9+ は不変リストArrays.asList()サイズ固定(追加/削除不可、要素変更可)
  • Collections.unmodifiableList()ビュー。元のリストが変わると反映される
  • 実装選択の目安: 99% は ArrayList。先頭への追加が多いなら ArrayDeque 検討(LinkedList より速い)

List とは

Listjava.util.List インターフェースで、Java Collections Framework の代表格です。要素の順序を保ち、重複を許すコレクションを抽象化しており、複数の具体実装が用意されています。

import java.util.*;

// インターフェース宣言、ArrayList 実装
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Alice");       // 重複 OK

System.out.println(names);          // [Alice, Bob, Alice]
System.out.println(names.size());   // 3
System.out.println(names.get(0));   // Alice
names.set(0, "Carol");              // 上書き
names.remove(1);                    // インデックス1削除

主要メソッド

メソッド役割
add(e)末尾に追加
add(i, e)位置 i に挿入
get(i)位置 i の要素取得
set(i, e)位置 i を e で置換
remove(i) / remove(Object)削除
indexOf(e) / lastIndexOf(e)位置検索
contains(e)含まれるか
subList(from, to)部分リスト(ビュー)
size()要素数
isEmpty()空か
iterator() / listIterator()反復
toArray()配列化
stream()Stream 化
sort(Comparator) Java 8+ソート

主要実装の比較

実装内部構造get(i)add(末尾)add(0)remove(i)用途
ArrayList動的配列O(1)償却 O(1)O(n)O(n)汎用、デフォルト選択
LinkedList双方向連結リストO(n)O(1)O(1)O(n)先頭/末尾の追加削除多発(Deque 推奨)
Vector動的配列 + synchronizedO(1)O(1)O(n)O(n)レガシー(非推奨)
CopyOnWriteArrayList配列、書込時にコピーO(1)O(n)O(n)O(n)読み多・書き少の並行処理

ArrayList の使い方

import java.util.*;

// 初期容量指定(要素数が予測できる場合は推奨)
List<Integer> list = new ArrayList<>(1000);

for (int i = 0; i < 1000; i++) {
    list.add(i);
}

// 走査(拡張 for)
for (Integer n : list) {
    System.out.println(n);
}

// イテレータ(途中削除可能)
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
    if (it.next() % 2 == 0) it.remove();
}

// Stream(関数型)
List<Integer> evens = list.stream()
    .filter(n -> n % 2 == 0)
    .toList();      // Java 16+ で immutable List 返す

LinkedList と ArrayDeque

「先頭/末尾の追加削除が多いなら LinkedList」と語られがちですが、実務では ArrayDeque の方が速いケースが多いです:

// LinkedList は List + Deque を兼ねる
LinkedList<String> ll = new LinkedList<>();
ll.addFirst("A");
ll.addLast("B");
ll.removeFirst();

// ArrayDeque は Deque のみ。List ではない。
// が、ノード allocate が無いため LinkedList より速い
Deque<String> dq = new ArrayDeque<>();
dq.push("A");           // 先頭追加
dq.offer("B");          // 末尾追加
dq.poll();              // 先頭取り出し

// 結論: List インターフェースが必要なら ArrayList。
// FIFO/LIFO/Deque 用途なら ArrayDeque。

不変リスト (Immutable List)

// Java 9+ : List.of() で不変リスト
List<String> imm = List.of("A", "B", "C");
imm.add("D");       // ❌ UnsupportedOperationException

// 旧来の方法
List<String> imm2 = Collections.unmodifiableList(
    new ArrayList<>(Arrays.asList("A", "B", "C"))
);

// Arrays.asList は ★ サイズ固定 ★ で完全不変ではない
List<String> fixed = Arrays.asList("A", "B", "C");
fixed.set(0, "Z");   // ✅ OK(要素変更は可)
fixed.add("D");      // ❌ UnsupportedOperationException

// Java 10+ : copyOf で防御的コピーの不変リスト
List<String> copy = List.copyOf(mutableList);

3 種類の "不変っぽい" リスト比較

方法add / removeset元データの変更
List.of()不可不可影響なし(完全不変)
Arrays.asList()不可配列を共有(変更が反映)
Collections.unmodifiableList()不可不可元リストの変更が反映(ビュー)

並行処理での List

// ❌ ArrayList は非スレッドセーフ。複数スレッド書込みでデータ破損
List<String> unsafe = new ArrayList<>();

// 方法1: synchronized ラッパー
List<String> syncList = Collections.synchronizedList(new ArrayList<>());

// 方法2: CopyOnWriteArrayList(読み多・書き少向け)
List<String> cow = new CopyOnWriteArrayList<>();
cow.add("A");          // 書き込み毎に内部配列をコピー(O(n))
cow.forEach(System.out::println);   // 書込みと並行しても安全

// 方法3: 不変リスト(最も安全)
List<String> imm = List.copyOf(source);

よくある落とし穴

症状原因対処
ConcurrentModificationExceptioniterate 中に add/removeIterator#remove() / CopyOnWrite
UnsupportedOperationException on add不変リスト / Arrays.asListnew ArrayList<>(asList(…))
大量データで性能劣化初期容量未指定で再 allocate 多発new ArrayList<>(N)
List.of(null) でエラーList.of は null 禁止Arrays.asList / 自前リスト
subList 後に元リストを変更したら failsubList は "ビュー"独立コピーが必要なら new ArrayList<>(sub)

FAQ

Q: ArrayList と LinkedList、どちらを使えば良い?
A: 99% は ArrayList。理由は キャッシュ効率(配列の連続メモリ)と get(i) が O(1) であること。LinkedList が勝るのは「先頭/末尾の頻繁な追加削除」だが、その用途は ArrayDeque の方が更に高速。

Q: List.of の最大要素数は?
A: Java 9 では of(e1)of(e1...e10)固定オーバーロードと、可変長 of(E... elements) があり実質無制限。10 個まではオートボクシング無しの最適化があります。

Q: スレッドセーフな List が欲しい
A: 読み多なら CopyOnWriteArrayList、読み書き均等なら Collections.synchronizedList、可能なら不変リストList.copyOf)が最も安全。