JavaのListをマスター!ArrayListとLinkedListの違いと使い方を徹底解説
生徒
「Javaで複数のデータをまとめて管理したいとき、配列を使っていますが、後から要素を増やせなくて困っています。」
先生
「配列はサイズが固定ですからね。そんな時は、Javaの『List(リスト)』を使うと便利ですよ。データの追加や削除が自由自在にできます。」
生徒
「ListにはArrayListやLinkedListなどいくつか種類があると聞いたのですが、どう使い分ければいいのでしょうか?」
先生
「それぞれの特徴を理解すれば、状況に合わせて最適な方を選べるようになります。まずは基本的な使い方から順番に学習していきましょう!」
1. JavaのListとは?配列との違いを解説
Javaのプログラミングでは、複数のデータをまとめて扱う仕組みをコレクションと呼びます。その中でも特に使用頻度が高く、初心者から実務まで幅広く使われているのがList(リスト)です。Listは、データを入力した順番どおりに保持でき、同じ値を何度でも格納できるという特徴を持っています。
多くの初心者が最初につまずくポイントが、配列との違いです。配列は作成時にサイズを決める必要があり、後から要素数を変更できません。一方でListは、プログラムの実行中でも自由に要素を追加・削除できます。そのため、データ数が事前に分からない場面や、状況に応じて内容が変わる処理に非常に向いています。
また、Listは「インターフェース」という設計図のような存在で、実際の処理はArrayListやLinkedListといったクラスが担当します。まずは「Listは柔軟に使える入れ物」というイメージを持つことが、理解への近道です。
ここで、プログラミング未経験者でも分かりやすい、簡単なサンプルを見てみましょう。これは「買い物メモ」をListで管理する例です。
import java.util.ArrayList;
import java.util.List;
public class ListIntroExample {
public static void main(String[] args) {
// Listの作成(買い物メモ)
List<String> memo = new ArrayList<>();
// データを追加
memo.add("牛乳");
memo.add("パン");
memo.add("卵");
// 中身を表示
System.out.println(memo);
}
}
このようにListを使えば、「あとから追加できる」「順番が保たれる」「まとめて管理できる」といったメリットを、難しい設定なしで活用できます。配列よりも直感的に扱えるため、Java学習では早い段階でListに慣れておくことがとても重要です。
2. ArrayListの基本概念と特徴
ArrayList(アレイリスト)は、Javaの中で最も一般的に利用されるListの実装クラスです。内部的には配列を利用してデータを保持していますが、容量が足りなくなると自動的に拡張してくれる仕組みを持っています。
ArrayListの大きな特徴は、「データの参照(取り出し)が非常に速い」という点です。各要素にインデックス番号(添え字)が割り振られており、特定の場所にあるデータに一瞬でアクセスできます。そのため、データの検索や読み込みが中心となる処理に適しています。
一方で、要素の途中にデータを挿入したり、途中のデータを削除したりする処理は、後続の要素を一つずつずらす必要があるため、データ量が多くなると処理が重くなるという側面もあります。しかし、日常的な開発の多くではこのArrayListが標準的に選択されます。
まずは、ArrayListを使って文字列のリストを作成し、要素を追加・表示するシンプルなコードを見てみましょう。
import java.util.ArrayList;
import java.util.List;
public class ArrayListBasic {
public static void main(String[] args) {
// ArrayListの作成
List<String> fruits = new ArrayList<>();
// 要素の追加
fruits.add("リンゴ");
fruits.add("バナナ");
fruits.add("オレンジ");
// 要素の取得と表示
System.out.println("1番目のフルーツ: " + fruits.get(0));
System.out.println("全てのフルーツ: " + fruits);
}
}
1番目のフルーツ: リンゴ
全てのフルーツ: [リンゴ, バナナ, オレンジ]
3. LinkedListの基本概念と特徴
LinkedList(リンクドリスト)は、日本語で「連結リスト」と呼ばれます。ArrayListとは異なり、各要素が自分の前後の要素への参照(リンク)を持っている構造をしています。
この構造のメリットは、「要素の挿入や削除が非常に速い」という点です。例えば、リストの途中に新しいデータを追加する場合、前後のリンクを繋ぎ変えるだけで済むため、ArrayListのようにデータを後ろへずらす手間がかかりません。
ただし、デメリットとして「特定の要素へのアクセスが遅い」という特徴があります。LinkedListで5番目の要素を探すには、先頭から順番にリンクを辿っていく必要があるため、ランダムアクセスには不向きです。大量のデータを頻繁に書き換えたり、リストの先頭や末尾に対して操作を行ったりする場合にその真価を発揮します。
次に、LinkedListを使用して数値(整数)を管理する例を確認しましょう。
import java.util.LinkedList;
import java.util.List;
public class LinkedListExample {
public static void main(String[] args) {
// LinkedListの作成
List<Integer> numbers = new LinkedList<>();
// 要素の追加
numbers.add(100);
numbers.add(200);
// 途中に要素を挿入
numbers.add(1, 150); // インデックス1の位置に挿入
// 要素の削除
numbers.remove(Integer.valueOf(200)); // 値を指定して削除
for (Integer num : numbers) {
System.out.println("数値: " + num);
}
}
}
数値: 100
数値: 150
4. Listでよく使われる共通メソッド一覧
ArrayListもLinkedListも、同じ「Listインターフェース」を継承しているため、基本的な使い方は共通しています。初心者がまず覚えるべき主要なメソッドを整理しましょう。
| メソッド名 | 説明 |
|---|---|
| add(要素) | リストの末尾に新しい要素を追加します。 |
| get(インデックス) | 指定した位置にある要素を取得します。 |
| set(インデックス, 要素) | 指定した位置の要素を新しい内容で上書きします。 |
| remove(インデックス) | 指定した位置の要素を削除します。 |
| size() | リストに含まれている要素の数を返します。 |
| clear() | リスト内の全ての要素を削除して空にします。 |
| contains(要素) | リストに特定の要素が含まれているか確認します。 |
これらのメソッドを組み合わせることで、データの登録、参照、更新、削除といった、いわゆる「CRUD処理」を簡単に行うことができます。特にsize()メソッドは、繰り返し処理(for文)と組み合わせて使うことが多いため、必ず覚えておきましょう。
5. 拡張for文を使ったListのループ処理
Listに格納されたデータを一つずつ取り出して処理を行う際、Javaでは「拡張for文」を使うのが一般的です。従来のfor文よりも記述がシンプルで、読み間違い(バグ)を減らすことができます。
拡張for文は「リストの中身を全部順番に見る」という目的において、最も読みやすい書き方です。インデックス番号を意識する必要がないため、コードが非常にスッキリします。
以下のサンプルプログラムでは、ユーザー名のリストを作成し、拡張for文を使って全員分の挨拶を表示しています。また、リストのサイズを確認する方法も併せて紹介します。
import java.util.ArrayList;
import java.util.List;
public class ListLoopExample {
public static void main(String[] args) {
List<String> users = new ArrayList<>();
users.add("田中さん");
users.add("佐藤さん");
users.add("鈴木さん");
// リストのサイズを取得
System.out.println("登録人数: " + users.size() + "名");
// 拡張for文で繰り返し処理
for (String user : users) {
System.out.println("こんにちは、" + user + "!");
}
}
}
登録人数: 3名
こんにちは、田中さん!
こんにちは、佐藤さん!
こんにちは、鈴木さん!
6. ジェネリクス(Generics)の重要性
Listを宣言する際に使う<String>や<Integer>という記述をジェネリクス(型引数)と呼びます。これは「このリストには何型のデータを入れるか」をコンパイラに伝える仕組みです。
Javaの古いバージョンでは、どんなオブジェクトでも入れられるリストが使われていましたが、それだと取り出す際に「これは文字列なのか数値なのか」をいちいち判定しなければならず、エラーの原因になっていました。ジェネリクスを使うことで、指定した型以外のデータが入るのを防ぎ、安全にプログラミングができるようになります。
なお、intやdoubleなどの基本データ型をそのままジェネリクスに指定することはできません。代わりに、ラッパークラス(Integer, Double, Booleanなど)を使用するという点に注意してください。この自動変換の仕組みを「オートボクシング」と呼びますが、初心者の方は「リストには大文字から始まる型名を使う」と覚えておけば大丈夫です。
7. ArrayListとLinkedListの使い分け基準
結局のところ、どちらを使えば良いのか迷うこともあるでしょう。判断基準をシンプルにまとめると以下のようになります。
- ArrayListを使うべきケース:
- データの追加が主に末尾のみである。
- 保存したデータをインデックス番号で頻繁に参照する。
- 特段の理由がない(迷ったらこちらを選ぶのが一般的)。
- LinkedListを使うべきケース:
- リストの先頭や途中に対して、頻繁に要素の挿入や削除を行う。
- データの件数が非常に多く、メモリの連続確保が難しい特殊な環境。
- スタックやキューのような「先入れ先出し」の構造を実装したい。
現代のコンピュータは非常に高速であるため、通常のアプリケーション開発で数千件程度のデータを扱うのであれば、ArrayListの方がメモリ効率も良く、速度面でも有利に働くことが多いです。実務レベルでも9割以上の場面でArrayListが採用されています。
8. 実践:Listを使ったデータの更新と削除
最後に、少し実用的なプログラムを作成してみましょう。買い物リストを想定し、リスト内のデータを検索して、特定の条件に一致するものを更新したり削除したりする流れを実装します。
このサンプルでは、リスト内に特定の項目があるかをcontainsメソッドで確認し、その位置をindexOfで取得して内容を書き換えるという、一連の操作を行っています。実際のシステム開発でもよく使われるロジックなので、ぜひ参考にしてください。
import java.util.ArrayList;
import java.util.List;
public class ShoppingListManager {
public static void main(String[] args) {
List<String> cart = new ArrayList<>();
cart.add("牛乳");
cart.add("卵");
cart.add("パン");
// 要素の更新:「卵」を「高級な卵」に変更
if (cart.contains("卵")) {
int index = cart.indexOf("卵");
cart.set(index, "高級な卵");
System.out.println("商品をアップグレードしました。");
}
// 要素の削除:「パン」を取り除く
cart.remove("パン");
System.out.println("現在のカート内:");
for (int i = 0; i < cart.size(); i++) {
System.out.println((i + 1) + "点目: " + cart.get(i));
}
}
}
商品をアップグレードしました。
現在のカート内:
1点目: 牛乳
2点目: 高級な卵
JavaのListは、今回紹介した以外にも多くの便利な機能を持っています。Stream APIを使った高度なフィルタリングや、Collectionsクラスを使った並べ替え(ソート)など、ステップアップするための要素はたくさんあります。まずはArrayListの基本操作をしっかりと身につけ、自由にデータを操れるようになりましょう!