Java入門 #16 - List と LinkedList の違い

入門 | 10分 で読める | 2026.05.02

公式ドキュメント

この記事の要点

List はインターフェース、ArrayList / LinkedList は実装クラス
• ArrayList はランダムアクセスが速い、LinkedList は挿入・削除が速い
• `List.of()` で不変リストを簡潔に作成できる(Java 9以降)

List インターフェースとは

前回(#15)で学んだ ArrayList は、実は List というインターフェースを実装したクラスの1つです。

インターフェースとは「こういうメソッドを持っていますよ」という契約のようなものです。List インターフェースは「順序を持つコレクション」の共通操作(add / get / remove など)を定義しています。

用語説明
Listインターフェース(契約)。順序を持つコレクションの共通仕様
ArrayListList を実装したクラス。内部で配列を使用
LinkedListList を実装したクラス。内部で双方向リンクリストを使用

ポイント: コードでは変数の型を `List` にしておき、生成時に `ArrayList` か `LinkedList` かを選ぶのが一般的です。これをプログラミング・トゥ・インターフェースと呼びます。

List 型で宣言する利点

// Java 21
import java.util.List;
import java.util.ArrayList;

// 推奨: 型は List、実装は ArrayList
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");

なぜ ArrayList<String> names ではなく List<String> names とするのか?

メリット説明
柔軟性後で LinkedList に変更しても、利用側のコードは変わらない
テスト容易性モック(テスト用ダミー)に差し替えやすい
設計の明確化「順序付きリストであればOK」という意図が伝わる

ArrayList と LinkedList の違い

どちらも List インターフェースを実装していますが、内部構造が異なります。

項目ArrayListLinkedList
内部構造可変長配列(連続メモリ)双方向リンクリスト(ノードのつながり)
ランダムアクセス(get)O(1)(超高速)O(n)(遅い)
末尾追加(add)O(1)(平均)O(1)
先頭・途中挿入O(n)(要素をずらす)O(1)(ポインタ変更のみ)
途中削除O(n)(要素を詰める)O(1)(ポインタ変更のみ)
メモリ効率良いやや悪い(各ノードにポインタが必要)
用途一般的なリスト操作全般(デフォルト)頻繁な挿入・削除がある場合

注意: 特に理由がなければArrayListを使ってください。LinkedList は挿入・削除が多い特殊なケースでのみ有利です。

パフォーマンス比較の実例

以下の操作を10万回繰り返した場合の計算量イメージです。

操作ArrayListLinkedList速いのは
get(i) で全要素読み取りO(n)O(n²)ArrayList
add(0, element) で先頭挿入O(n²)O(n)LinkedList
remove(0) で先頭削除O(n²)O(n)LinkedList
add(element) で末尾追加O(n)O(n)ほぼ同じ

補足: LinkedList は Queue(キュー)や Deque(両端キュー)として使うために設計されています。スタックやキュー操作が必要な場合に検討してください。

LinkedList の基本操作

基本的なメソッドは ArrayList と同じですが、LinkedList 特有のメソッドもあります。

// Java 21
import java.util.LinkedList;

LinkedList<String> queue = new LinkedList<>();

// 末尾に追加(ArrayList と同じ)
queue.add("Alice");
queue.add("Bob");

// 先頭に追加(LinkedList 特有)
queue.addFirst("Charlie");  // ["Charlie", "Alice", "Bob"]

// 先頭を削除(LinkedList 特有)
String first = queue.removeFirst();  // "Charlie"

// 末尾を削除(LinkedList 特有)
String last = queue.removeLast();  // "Bob"
LinkedList 特有メソッド説明
addFirst(E)先頭に追加
addLast(E)末尾に追加(add と同じ)
removeFirst()先頭を削除して返す
removeLast()末尾を削除して返す
getFirst()先頭を取得(削除しない)
getLast()末尾を取得(削除しない)

ポイント: これらのメソッドは Queue / Deque インターフェースからも提供されます。LinkedList は QueueDeque の両方を実装しています。

List の主要メソッド(共通)

ArrayList と LinkedList の両方で使える主要メソッドです。

メソッド説明戻り値
add(E element)末尾に追加boolean
add(int index, E element)指定位置に挿入void
get(int index)指定位置の要素を取得E
set(int index, E element)指定位置を上書きE
remove(int index)指定位置を削除E
remove(Object o)指定値を削除(最初の1件)boolean
size()要素数int
isEmpty()空かどうかboolean
contains(Object o)要素が含まれるかboolean
clear()全削除void

不変リスト(List.of)

不変リストは、一度作ったら追加・削除・変更ができないリストです。Java 9 以降、List.of() で簡潔に作成できます。

// Java 21
import java.util.List;

// 不変リストを作成
List<String> colors = List.of("Red", "Green", "Blue");

System.out.println(colors.get(0));  // Red
System.out.println(colors.size());  // 3

// 変更しようとするとエラー
// colors.add("Yellow");  // UnsupportedOperationException
特徴説明
不変add / remove / set が使えない(実行時エラー)
簡潔new ArrayList<>(Arrays.asList(...)) より短い
null 禁止List.of(null)NullPointerException
軽量内部構造が最適化されている

注意: 不変リストに変更操作(add / remove / set)を実行すると `UnsupportedOperationException` が発生します。

実践例: タスク管理(先頭挿入が頻繁)

先頭への挿入が頻繁な場合、LinkedList が有利です。

// Java 21
import java.util.LinkedList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        LinkedList<String> tasks = new LinkedList<>();

        // タスクを追加(先頭に緊急タスクを挿入する運用)
        tasks.add("メールチェック");
        tasks.add("資料作成");
        tasks.addFirst("緊急:バグ修正");  // 先頭に挿入

        System.out.println("現在のタスク:");
        for (String task : tasks) {
            System.out.println("- " + task);
        }

        // 先頭から順次処理
        while (!tasks.isEmpty()) {
            String current = tasks.removeFirst();
            System.out.println("処理中: " + current);
        }
    }
}

出力:

現在のタスク:
- 緊急:バグ修正
- メールチェック
- 資料作成
処理中: 緊急:バグ修正
処理中: メールチェック
処理中: 資料作成

選択のガイドライン

状況推奨理由
一般的なリスト操作ArrayListランダムアクセスが速く、メモリ効率も良い
インデックスでの頻繁な読み取りArrayListget(i) が O(1)
先頭・途中への頻繁な挿入LinkedListポインタ変更のみで O(1)
キュー(FIFO)LinkedListaddLast() / removeFirst() が効率的
スタック(LIFO)LinkedList または ArrayDequeaddFirst() / removeFirst()
読み取り専用List.of()不変で安全、軽量

ポイント: 迷ったらArrayListを使いましょう。ほとんどのケースで最速です。LinkedList は「先頭挿入が超頻繁」「キュー実装」など明確な理由がある場合のみ選択してください。

まとめ

概念説明
List順序付きコレクションのインターフェース
ArrayList配列ベースの実装。ランダムアクセス O(1)、一般用途に最適
LinkedListリンクリストベースの実装。先頭挿入・削除 O(1)、キュー向き
プログラミング・トゥ・インターフェースList<String> で宣言し、実装を後で変更可能にする
List.of()不変リストを簡潔に作成(Java 9以降)
パフォーマンス一般には ArrayList、先頭操作が多いなら LinkedList

次のステップ

Java入門 #17 - HashMap(キーと値のペア) で、キーと値を関連付けるマップ(辞書)を学びます。

参考リソース

この技術を体系的に学びたいですか?

未来学では東証プライム上場企業のITエンジニアが24時間サポート。月額24,800円から、退会金0円のオンラインIT塾です。

メールで無料相談する
← 一覧に戻る