![]()
【Java入門 実用編】ArrayList クラスの基本的な利用 | Java のコレクションクラス
2025.11.21
Javaのコレクションフレームワークの中で、最も頻繁に利用されるのが List インターフェイスと、その実装クラスである ArrayList です。データの順序を保ちながら、可変長の配列のように扱えるこの仕組みは、Java開発の基礎中の基礎と言えます。
本記事では、List インターフェイスの特徴や、実務で必須となる ArrayList の基本的な操作方法などについて、サンプルコードを交えて解説します。
List インターフェイス
List は、java.util パッケージに含まれるインターフェイスであり、順序付けられた要素の集まり(シーケンス)を表します。
List インターフェイスの特徴
List インターフェイスには、大きく分けて以下の3つの特徴があります。
要素の順序が維持される
List に追加された要素は、追加した順番を保持します。配列と同様に「インデックス(添字)」を持っており、0から始まる番号で特定の位置にある要素にアクセスしたり、操作したりすることができます。
要素の重複が許される
List は数学的な「集合(Set)」とは異なり、同じ要素を複数格納することが可能です。例えば、文字列のリストで ["A", "B", "C, "A"] のように、同じ値の文字列である "A" が複数回登場しても問題ありません。これは文字列に限らず、Java Bean のインスタンスなどの場合も同じです。
また、代表的な実装クラスである ArrayList では null を要素として格納することも可能です。(他の実装クラスについては実装に依存します)
格納しているのは参照
Java の List に格納されるのは、オブジェクトそのものではなく、ヒープ領域にあるオブジェクトへの参照です。 そのため、int、doubleなどの基本データ型(プリミティブ型)を直接格納することはできません。
List でこれらを扱う場合は、対応するラッパークラス(Integer, Doubleなど)を使用する必要がありますJava5以降はオートボクシング機能により、見た目上は直接入れているように記述できますが、実際に格納されているのはオブジェクトへの参照であることに注意してください。
また、同じインスタンスへの参照を複数回格納している場合、参照先のオブジェクトに変更を加えると、同じ参照を持つ要素(実体は同じ)へ反映されることにも注意が必要です。
ArrayList クラスの基本的な利用
ここでは、List インターフェイスの最も代表的な実装クラスである ArrayList クラスの基本的な利用方法と、主なメソッドについて説明します。
インスタンス生成とジェネリクス
ArrayList の利用にはインスタンス(オブジェクト)を生成する必要があります。インスタンスの生成時は、ジェネリクス(Generics)という機能を使い、「このリストにどの型のデータを格納するか」を指定するのが一般的です。ジェネリクスによりリストに格納する型を指定した場合は、指定した型またはその継承先クラスのみリストに格納することができます。
また、型の指定を省略した場合は、全てのクラスを格納することが可能ですが、要素の取り出し時は Object クラスとして扱われます。ソースの可読性および安全性のため、基本的には型を指定して利用します。
import java.util.ArrayList;
import java.util.List;
public class CreateListSample {
public static void main(String[] args) {
// 基本形: String型(およびそのサブクラス)のみ格納可能なリスト
// 右辺の <> 内の型は省略可能(ダイヤモンド演算子)
List<String> names = new ArrayList<>();
// 数値を扱う場合: int などのプリミティブ型は指定できないため
// ラッパークラスである Integer を指定
List<Integer> numbers = new ArrayList<>();
// 【参考】継承先クラスの格納例
// Number型を指定すると、IntegerやDoubleなどのサブクラスは全て格納可能
List<Number> numList = new ArrayList<>();
numList.add(10); // Integer
numList.add(3.14); // Double
}
}追加・挿入(add メソッド)
ArrayList に新しい要素を加えるには add メソッドを使用します。
add メソッドで追加する要素のみを引数として渡した場合、要素は ArrayList の一番最後に追加されます。ArrayList では要素の順番が保持されます。
メソッド: boolean add(E e)
List<String> team = new ArrayList<>();
team.add("Sato");
team.add("Suzuki");
team.add("Tanaka");
// 0番目: Sato, 1番目: Suzuki, 2番目: Tanaka となる
add メソッド(オーバーロードメソッド)の引数に要素を追加する位置(0から始まるインデックス)を指定した場合、ArrayList の任意の位置に要素を挿入することができます。要素を挿入したインデックスより後ろにあった要素の位置は後ろにずれます。
この時、挿入する位置としてArrayList の要素数と同じ値を指定した場合は一番最後に追加されます。0 未満の値や要素数より大きい値を指定した場合は例外(IndexOutOfBoundsException)がスローされます。
メソッド: void add(int index, E element)
List<String> alphabets = new ArrayList<>();
alphabets.add("A"); // [0番目: "A"]
alphabets.add("C"); // [0番目: "A", 1番目: "C"]
// インデックス:1 の位置に"B"を挿入
alphabets.add(1, "B"); // [0番目: "A", 1番目: "B", 2番目: "C"]
// 挿入する位置に負の値や要素数より大きい値を指定するとエラー
alphabets.add(26, "Z"); // IndexOutOfBoundsException が発生するまとめて追加(addAll メソッド)
別のリストやコレクションに含まれる要素を ArrayList に加えたい場合、addAll メソッドを使用することで一度にまとめて追加することができます。
add メソッド同様、追加する要素を含むコレクションのみを引数として渡した場合、要素は ArrayList の一番最後に追加されます。
メソッド: addAll(Collection<? extends E> c)
// 本体のリスト
List<String> mainList = new ArrayList<>();
mainList.add("Apple");
mainList.add("Banana");
// 追加したいリスト ※Java 9 以降であれば List.of で作成してもOK
List<String> additionalList = Arrays.asList("Cherry", "Durian");
// 末尾にまとめて追加
mainList.addAll(additionalList);
System.out.println("追加後: " + mainList); //["Apple", "Banana", "Cherry", "Durian"]
第一引数に要素を追加する位置(0から始まるインデックス)を指定した場合、ArrayList の任意の位置から引数のコレクション内に含まれる全ての要素を挿入します。要素を挿入したインデックスより後ろにあった要素の位置は、追加された要素の数だけ後ろにずれます。
add メソッド同様、このとき挿入する位置としてArrayList の要素数と同じ値を指定した場合は一番最後に追加されます。0 未満の値や要素数より大きい値を指定した場合は例外(IndexOutOfBoundsException)がスローされます。
メソッド: boolean addAll(int index, Collection c)
// 本体のリスト
List<String> mainList = new ArrayList<>();
mainList.add("A");
mainList.add("D");
System.out.println("挿入前: " + mainList); // ["A", "D"]
// 挿入対象のリストを準備
List<String> insertList = Arrays.asList("B", "C");
// インデックス1の位置にまとめて挿入("D" は後ろにずれる)
mainList.addAll(1, insertList);
System.out.println("挿入後: " + mainList); // ["A", "B", "C", "D"]
いずれの場合も、引き渡したコレクションが空のコレクションの場合は false を返します。また、引数のコレクションに null を指定した場合は例外(NullPointerException)が発生することに注意してください。
削除(remove メソッド)
ArrayList から要素を削除(除去)するには remove メソッドを使用します。リストから除去する要素を指定するには、引数で「要素の位置(インデックス)」または「要素に含まれているオブジェクト(中身)」のいずれかを指定します。
要素の位置を指定した場合は、戻り値に除去した要素が返ります。
メソッド:E remove(int index)
List<String> cities = new ArrayList<>();
cities.add("Tokyo");
cities.add("Osaka");
cities.add("Fukuoka");
cities.add("Sapporo");
// インデックス2 ("Fukuoka") を削除(戻り値で削除された文字列を受け取れる)
String removedCity = cities.remove(2);
System.out.println("削除された都市: " + removedCity); // Fukuoka
除去するオブジェクトを指定する場合は、リストに含まれている要素と equals メソッドで比較して同じとみなされる要素を指定します。(異なるインスタンスでも equals メソッドで true が返るインスタンスが除去されることに注意してください)
除去された場合は true、除去されない(指定したオブジェクトがリストに含まれていなかった)場合は false が返ります。また、リストに同じ要素が複数個含まれていた場合は、先頭から見て最初の1個だけが除去されます。
List<String> cities = new ArrayList<>();
cities.add("Tokyo");
cities.add("Osaka");
cities.add("Fukuoka");
cities.add("Sapporo");
// new String で別の文字列インスタンス(値は同じ"Osaka")を指定して削除
boolean result1 = cities.remove(new String("Osaka"));
System.out.println("Osakaを削除: " + result1); // true
// リストにない値("Nagoya")を削除
boolean result2 = cities.remove(new String("Nagoya"));
System.out.println("Nagoyaを削除: " + result2); // false比較的利用されるメソッド
要素の個数(size メソッド)
リストに格納されている要素の数を確認するには size メソッドを使用します。
メソッド: int size()
List<String> items = new ArrayList<>();
items.add("Pen");
items.add("Notebook");
// 要素数を取得
int count = items.size();
System.out.println("現在の要素数: " + count); // 2
リストが空かどうかのチェックをする場合は、size メソッドで取得した値が 0 であることを確認する以外に、isEmpty メソッドを利用することでも確認できます。
メソッド: boolean isEmpty()
List<String> items = new ArrayList<>();
// リストが空かどうかをチェック
System.out.println("リストが空: " + items.isEmpty()); // true
// 要素を追加
items.add("Notebook");
// 再度リストが空かどうかをチェック
System.out.println("リストが空: " + items.isEmpty()); // false要素の置き換え(set メソッド)
指定した位置(インデックス)にある要素を、新しい要素に差し替えます。元々リストの指定位置にあった要素はリストから除去され、メソッドの戻り値として返されます。
メソッド: E set(int index, E element)
List<String> colors = new ArrayList<>();
colors.add("Red");
colors.add("Blue");
colors.add("Green");
System.out.println("変更前: " + colors); //["Red", "Blue", "Green"]
// インデックス=1 の要素 ("Blue") を "Yellow" に置き換え
String oldColor = colors.set(1, "Yellow");
System.out.println("変更後: " + colors); //["Red", "Yellow", "Green"]
System.out.println("上書きされた要素: " + oldColor); // "Blue"特定の要素を含むかの判定(contains メソッド)
リストの中に、引数で指定したオブジェクトと同じ要素が含まれているかどうかを返します。これは要素の重複チェックなどに利用することができます。
引数のオブジェクトと同じ要素があるかどうかは、オブジェクトの equals メソッドで true が返るものがあるかどうかで判定します。また、ArrayList では引数に null を引き渡した場合でもエラーとはならず、リスト が null の要素を持つかどうかを判定して返します。
メソッド: boolean contains(Object o)
List<String> members = new ArrayList<>();
members.add("Alice");
members.add("Bob");
// "Alice" が含まれているか確認
System.out.println("「Alice」を含む: " + members.contains("Alice")); // true
// "Charlie" が含まれているか確認
System.out.println("「Charlie」を含む: " + members.contains("Charlie")); // false
// null が含まれているか確認
System.out.println("nullを含む: " + members.contains(null)); // false特定の要素の位置を取得(indexOf メソッド)
リストの中に、引数で指定したオブジェクトと同じ要素が含まれている「位置」(インデックス)を返します。contains メソッドと同様に、同じ要素かどうかはオブジェクトの equals メソッドで true が返るものかどうかで判定します。
引数に null を指定した場合は、リストに null の要素が格納されている位置を返します。また、複数個同じ要素を含む場合は最初の位置(最小のインデックス)、含まれてないかった場合は -1 を返します。
メソッド: int indexOf(Object o)
List<String> members = new ArrayList<>();
members.add("Alice");
members.add("Bob");
members.add("Charlie");
members.add(null);
members.add("Bob");
// "Alice" の位置を確認
System.out.println("「Alice」の位置: " + members.indexOf("Alice")); // 0
// "Bob" の位置を確認(複数含む場合は最初の位置)
System.out.println("「Bob」の位置: " + members.indexOf("Alice")); // 1
// null が含まれているか確認
System.out.println("nullを含む: " + members.contains(null)); // false一部のリスト(のビュー)を切り出し(subList メソッド)
リストの一部分を切り出して、新しいリストとして返します。切り出し範囲は切り出し元のリストのインデックス(開始位置/終了位置)で指定します(開始位置から終了位置の1つ前までを切り出す)。開始位置と終了位置が同じ値の場合は空のリストが返されます。
◆ 親リストとの関係(ビュー)について
切り出したリストは、切り出し元のリストから指定した範囲へのリンクとして生成されるため、以下の点に注意が必要です。
- 子リストを変更した場合: 切り出し元リストの「指定した範囲」にも変更が反映されます。
- 親リストを変更した場合: 切り出し後に切り出し元リストに対して要素の追加や削除などの変更があった場合、切り出した子リストは整合性が取れなくなるため利用できなくなります(アクセス時に例外 ConcurrentModificationException が発生することがあります)。
◆ 例外の発生について
引数に渡した開始位置が負の値の場合や、終了位置が切り出し元リストの要素数より大きい場合は例外 IndexOutOfBoundsException が、また開始位置が終了位置より大きい値の場合は例外 IllegalArgumentException がスローされます。
メソッド: List<E> subList(int fromIndex, int toIndex)
List<Integer> numbers = new ArrayList<>();
numbers.add(10); // index:0
numbers.add(20); // index:1
numbers.add(30); // index:2
numbers.add(40); // index:3
numbers.add(50); // index:4
// 開始位置:1 終了位置:4 を指定して切り出し(1,2,3 の位置の要素が切り出される)
List<Integer> sub = numbers.subList(1, 4);
System.out.println("切り出したリスト: " + sub); // [20, 30, 40]配列への変換(toArray メソッド)
他のメソッドの引数として利用したい場合など、リストの要素を配列に変換するには toArray メソッドを利用します。toArray メソッドで作成された配列は、リストに含まれる要素数の長さの配列が生成されます。
引数を指定しない場合は Object クラスの配列が返されますが、通常は型の安全性を考慮して配列の型を引数で指定することを推奨します。
メソッド: Object[] toArray() ※型を指定しない場合は Object クラスの配列
メソッド: <T> T[] toArray(T[] a) ※配列の型を指定する場合は引数で指定する
List<String> languages = new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("Ruby");
// List を String配列に変換
// new String[0] を渡すことで、戻り値の型を String[] に確定させます
String[] langArray = languages.toArray(new String[0]);
System.out.println("配列の先頭の要素: " + langArray[0]); // "Java"
System.out.println("配列の長さ: " + langArray.length); // 3反復子(イテレータ)への変換(iterator メソッド)
リストの要素を順番に取り出すための「反復子(Iterator)」を取得します。 subList メソッド同様に、取得した反復子はリストのデータとリンクしているため、元のリストに変更があった場合は利用できないことや、反復子への変更は元のリストに反映されることに注意が必要です。
配列と同様に他のメソッドの引数としてリストの要素を反復子として引き渡したい場合や、条件に合致する要素を Iterator を使うことでリストから安全に削除したいケースなどに利用できます。
メソッド: Iterator iterator()
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
fruits.add(null);
// Iteratorを取得
Iterator<String> it = fruits.iterator();
while (it.hasNext()) {
// 次の要素を取得
String fruit = it.next();
System.out.println("確認中: " + fruit);
// null か "Banana" ならリストから削除
if (fruit == null || "Banana".equals(fruit)) {
it.remove(); // 安全に削除
}
}
System.out.println("処理後のリスト: " + fruits); // ["Apple", "Orange"]

