JavaのArrayListとは?基本操作から実務活用まで徹底解説

この記事では、JavaのArrayListの基本操作から実務での活用方法まで、コードを交えて解説します。

Zettoのライタープロフィール

ArrayListを理解していないと、データ管理に毎回配列を使い続けることになり、コードが複雑になりがちです。実務ではほぼ必ず登場するので、早めに押さえておきたいところです。

この記事を読めば、ArrayListの基本操作・繰り返し処理・実務での設計思想がわかり、Javaのコーディングがスムーズになります。

ぜひ参考にしてみてください。

目次

ArrayListとは?配列との違いをコードで比較する

ArrayListと配列の違い

まずはArrayListの基本を整理しておきましょう。

「配列で十分じゃないの?」と感じる方も、この章を読むと使い分けのイメージがつかめます。

  • ArrayListの概要とできること
  • 配列とArrayListの4つの違い
  • ArrayListを使うためのimport文と準備

順に見ていきましょう。

ArrayListの概要とできること

ArrayListは、Javaの標準ライブラリに含まれる「可変長リスト(サイズを後から変えられるリスト)」です。

配列と見た目は似ていますが、一番の違いは「後からデータを自由に追加・削除できる」点です。配列は宣言時に要素数を決めなければいけませんが、ArrayListはその必要がありません。

ArrayListでできることは以下の通りです。

  • 要素の追加:`add()`で末尾または任意の位置に追加できる
  • 要素の取得:`get()`でインデックス(番号)を指定して取得できる
  • 要素の削除:`remove()`で特定の要素を削除できる
  • サイズの確認:`size()`で現在の要素数がわかる
  • 要素の検索:`contains()`や`indexOf()`で特定の要素を探せる

実務でも、複数のデータをまとめて扱うときはArrayListを使う場面がとても多いです。

配列とArrayListの4つの違い

配列とArrayListの違いを整理すると、使い分けの判断がしやすくなります。

比較項目配列ArrayList
サイズ固定(変更不可)可変(後から追加・削除できる)
宣言方法String[] arr = new String[3]List<String> list = new ArrayList<>()
要素の追加不可(再作成が必要)add()で簡単に追加できる
型安全ジェネリクス(型の指定)が使えない使える

配列はパフォーマンスが高く、要素数が最初から決まっているケースに向いています。一方、ArrayListは「何件データが来るかわからない」という実務の場面でよく登場します。

コードで比較するとこんな感じです。

// 配列(サイズを最初に決める必要がある)
String[] fruits = new String[3];
fruits[0] = "apple";
fruits[1] = "banana";
fruits[2] = "orange";

// ArrayList(サイズを決めなくてよい)
ArrayList fruitList = new ArrayList<>();
fruitList.add("apple");
fruitList.add("banana");
fruitList.add("orange");
fruitList.add("grape"); // 後から追加できる

ArrayListはデータが増えても`add()`を呼ぶだけで対応できます。配列だと新しい配列を作り直す手間が発生します。

ArrayListを使うためのimport文と準備

ArrayListを使うには、ファイルの先頭にimport文を追加します。

import java.util.ArrayList;

これがないとコンパイルエラーになるので、忘れずに書きましょう。

実務では`import java.util.*`とワイルドカードでまとめてインポートするケースもありますが、IDEのオートインポート機能を使って個別にインポートする書き方の方が、可読性の観点から好まれることが多いです。

ここまでで、ArrayListの基本的なイメージがつかめたと思います。

Zetto

配列とArrayListの使い分けは最初に迷いやすいところです。「要素数が変わる可能性があるならArrayList」と覚えておくと、判断がしやすくなりますよ。

ArrayListの基本操作【宣言・追加・取得・削除・検索】

ArrayListの基本操作解説

ここからは、ArrayListの基本操作をコード付きで解説します。実際に手を動かしながら読み進めてみてください。

  • 宣言と初期化の書き方
  • 要素の追加(add)・取得(get)
  • 要素の削除(remove / clear)
  • サイズ確認(size)・検索(contains / indexOf)

1つずつ見ていきましょう。

宣言と初期化の書き方

ArrayListの宣言は以下のように書きます。

ArrayList list = new ArrayList<>();

`<String>`の部分はジェネリクス(型パラメーター)と呼ばれます。格納したい要素の型をここで指定します。

よく使う型の例はこちらです。

ArrayList nameList  = new ArrayList<>();   // 文字列
ArrayList scoreList = new ArrayList<>();  // 整数
ArrayList priceList  = new ArrayList<>();  // 小数

注意点として、`int`や`double`などのプリミティブ型(Javaの基本型)はそのまま使えません。代わりにラッパークラス(`Integer`・`Double`など)を使います。

初期値を設定したい場合は`Arrays.asList()`を使う方法もあります。

import java.util.Arrays;

ArrayList list = new ArrayList<>(Arrays.asList("apple", "banana", "orange"));

要素の追加(add)・取得(get)

要素の追加は`add()`、取得は`get()`を使います。

ArrayList list = new ArrayList<>();

// 末尾に追加
list.add("apple");
list.add("banana");
list.add("orange");

// インデックスを指定して追加(0番目の位置に挿入)
list.add(0, "grape");

// インデックスを指定して取得
String first  = list.get(0); // "grape"
String second = list.get(1); // "apple"

インデックスは0から始まります。配列と同じ感覚で使えるので、直感的に書けます。

`add(index, element)`のように位置を指定すると、挿入した位置以降の要素は自動的にずれます。手動でシフトする必要はありません。

要素の削除(remove / clear)

削除には`remove()`を使います。

ArrayList list = new ArrayList<>(Arrays.asList("apple", "banana", "orange"));

// インデックスで削除
list.remove(1); // "banana"を削除

// 値を指定して削除
list.remove("orange"); // "orange"を削除

// 全要素を削除
list.clear();

`ArrayList<Integer>`の場合には少し注意が必要です。`remove(1)`は「インデックス1番目を削除」、`remove(Integer.valueOf(1))`は「値1を削除」という動作になります。

ArrayList numList = new ArrayList<>(Arrays.asList(10, 20, 30));

numList.remove(0);                   // インデックス0番目(10)を削除
numList.remove(Integer.valueOf(20)); // 値20を削除

`int`と`Integer`の使い分けを間違えるとバグの原因になるので、頭に入れておきましょう。

サイズ確認(size)・検索(contains / indexOf)

`size()`でリストの要素数、`contains()`で要素の存在確認、`indexOf()`でインデックスの取得ができます。

ArrayList list = new ArrayList<>(Arrays.asList("apple", "banana", "orange"));

// サイズ確認
int size = list.size(); // 3

// 要素が含まれているか確認
boolean hasApple = list.contains("apple"); // true
boolean hasGrape = list.contains("grape"); // false

// 最初に一致する要素のインデックスを取得
int index    = list.indexOf("banana"); // 1
int notFound = list.indexOf("grape");  // -1(見つからない場合)

`indexOf()`は見つからない場合に`-1`を返します。存在確認だけなら`contains()`の方がシンプルで使いやすいです。

add・get・remove・size・containsの5つで、基本操作は一通り押さえられました。

Zetto

5つのメソッドを使いこなせれば、ArrayListの基本は十分です。まずはこれだけを手元で試してみてください。覚えようとするより、書いて動かす方が断然身につきますよ。

ArrayListをfor文で繰り返す3つの方法

ArrayListの反復処理方法

ArrayListの中身を全件処理するときは、繰り返し処理(ループ)を使います。Javaには複数の書き方があるので、使いどころを整理しておきましょう。

  • 拡張for文(for-each)で繰り返す
  • インデックス指定の通常for文
  • ラムダ式(forEach)を使う方法

それぞれ向いている場面が違うので、状況に合わせて選べるようにしておくといいですね。

拡張for文(for-each)で繰り返す

一番シンプルで読みやすいのが拡張for文(for-each)です。

ArrayList list = new ArrayList<>(Arrays.asList("apple", "banana", "orange"));

for (String fruit : list) {
    System.out.println(fruit);
}
// 出力:apple / banana / orange

「全件を順番に処理したいだけ」という場面では、この書き方が一番自然です。インデックスが不要なときは迷わずfor-eachを選びましょう。

注意点として、for-each中にリストの要素を削除しようとすると`ConcurrentModificationException`(同時変更の例外エラー)が発生します。削除が必要な場合は、後述の通常for文を使いましょう。

インデックス指定の通常for文

インデックス番号が必要な場面では、通常のfor文が向いています。

ArrayList list = new ArrayList<>(Arrays.asList("apple", "banana", "orange"));

for (int i = 0; i < list.size(); i++) {
    System.out.println(i + "番目: " + list.get(i));
}
// 出力:0番目: apple / 1番目: banana / 2番目: orange

「偶数番目だけ処理したい」「逆順に処理したい」「繰り返し中に要素を削除したい」といった細かい制御が必要なときに有効です。

繰り返しの中で要素を削除するときは、後ろから削除すると安全に動きます。

for (int i = list.size() - 1; i >= 0; i--) {
    if (list.get(i).equals("banana")) {
        list.remove(i);
    }
}

ラムダ式(forEach)を使う方法

Java 8以降では、ラムダ式(処理を簡潔に書くための記法)を使ったforEachが使えます。

ArrayList list = new ArrayList<>(Arrays.asList("apple", "banana", "orange"));

// ラムダ式
list.forEach(fruit -> System.out.println(fruit));

// メソッド参照を使うとさらに短く書ける
list.forEach(System.out::println);

コードが短くなるので、実務でもよく見かけます。ただ、処理が複雑になるほど読みにくくなることもあるので、シンプルな処理のときに使うのが自然です。

3つの方法をまとめると、使いどころが明確になります。

繰り返し方法向いている場面
拡張for文シンプルな全件処理
通常for文インデックス制御・要素の削除が必要な処理
ラムダ式forEachコードを短くまとめたいとき
Mirai

3つも方法があるんだね。最初はどれを使えばいいか迷いそう…

Zetto

最初は拡張for文だけ覚えれば大丈夫だよ。「インデックスが要るな」「もっと短く書きたいな」と感じたときに他の方法を試すと、自然に使い分けができるようになるよ!

実務で通用するArrayListの書き方と設計思想

ArrayListの実装パターン

基本操作を覚えたら、次は「現場で通用する書き方」を身につけましょう。コードが動くだけでなく、設計の意図を説明できるエンジニアになるためのステップです。

  • 「List<String> list = new ArrayList<>()」と書く理由
  • ArrayListとLinkedListの違いと使い分け
  • Java 9以降のList.of()との違い
  • 実務でArrayListが登場する具体的な場面
  • ArrayListの演習問題3つ

順に解説していきます。

「List<String> list = new ArrayList<>()」と書く理由

実務のコードを見ると、多くの場合こう書かれています。

// 実務でよく見る書き方
List list = new ArrayList<>();

// 初心者がやりがちな書き方
ArrayList list = new ArrayList<>();

左辺を`ArrayList`ではなく`List`(インターフェース)にする理由は、「後から実装クラスを変えやすくするため」です。

インターフェースとは「クラスが持つべき機能の約束事」のようなもので、`List`インターフェースを使って宣言しておくと、右辺だけ変えれば実装を切り替えられます。

// LinkedListに変えたいときは右辺だけ変えるだけでよい
List list = new LinkedList<>();

左辺を`ArrayList`にしていると、変更の影響がコード全体に及ぶ可能性が出てきます。これはオブジェクト指向の設計原則(インターフェースに依存する)と呼ばれる考え方で、実務では当たり前のように使われています。

僕が1社目で先輩のコードを読んだとき、最初はこの書き方の意味がわかりませんでした。でも理由を理解してからは、自分のコードにもこの書き方が自然と身についていきました。

Javaのコレクションフレームワーク全体の設計については、Oracle公式チュートリアルにわかりやすい解説があるので、あわせて読んでみてください。

ArrayListとLinkedListの違いと使い分け

ListインターフェースにはArrayListとLinkedListという2つの主な実装クラスがあります。どちらも似た使い方ができますが、内部の仕組みが違います。

要素の追加・削除が多い場合

要素の追加・削除が頻繁に起こる場合は、LinkedListが向いているとされています。

LinkedListは「連結リスト(各要素がポインターでつながった構造)」なので、途中への挿入・削除が得意です。ArrayListは内部が配列のため、途中に挿入するとそれ以降の要素をずらす処理が発生します。

List linkedList = new LinkedList<>();
linkedList.add("apple");
linkedList.add(0, "grape"); // 先頭への挿入

ただし、実務では「追加・削除が頻繁な場面」でもArrayListで十分なパフォーマンスが出ることがほとんどです。明確な理由がなければArrayListを使うのが無難かなと思います。

要素の取得・検索が多い場合

インデックスを指定して取得・検索する処理が多い場合は、ArrayListが向いています。

ArrayListは内部的に配列を使っているため、`get(index)`でのアクセスが高速です。処理量に関わらず常に一定の時間で完了します(O(1)と表記されます)。

List arrayList = new ArrayList<>();
arrayList.add("apple");
arrayList.add("banana");
String item = arrayList.get(1); // 高速に取得できる

WebアプリのバックエンドでDBから取得したデータを処理する場面では、ArrayListが圧倒的によく使われます。

Java 9以降のList.of()との違い

Java 9からは`List.of()`という書き方も使えます。

// List.of()で作成(変更不可のリスト)
List immutableList = List.of("apple", "banana", "orange");

// ArrayListで作成(変更可能)
List mutableList = new ArrayList<>(Arrays.asList("apple", "banana", "orange"));

`List.of()`で作ったリストは変更不可(イミュータブル)です。後から要素を追加・削除しようとすると`UnsupportedOperationException`が発生します。

使い分けのイメージはシンプルです。

  • `List.of()`:読み取り専用のリストを渡したいとき(変更させたくないデータ)
  • `ArrayList`:後から内容を変える可能性があるとき

実務でArrayListが登場する具体的な場面

実際に僕がフリーランスのJava案件(インフラ設備関連Webアプリ・大手商業施設の在庫管理システムなど)で経験した中で、ArrayListが登場した場面を挙げます。

実務での使用例は以下の通りです。

  • DBの検索結果をまとめて受け取る:`List<ユーザー>`のようなかたちでデータをまとめて処理する
  • 画面のドロップダウン選択肢を管理する:表示用データをArrayListで保持する
  • バリデーション(入力チェック)のエラーをまとめる:複数のエラーメッセージをリストで管理する
  • CSVやファイルの各行をリストとして処理する:読み込み後のデータ操作

特にSpring Bootを使ったWebアプリ開発では、ServiceクラスやRepositoryクラスで`List<エンティティ名>`というかたちが日常的に登場します。

ArrayListを試す演習問題3つ

ここまで学んだ内容を、実際に手を動かして確認しましょう。

この章では、3つの演習問題を用意しました。

  • 基本操作(追加・削除・表示)の練習
  • 繰り返し処理とArrayListを組み合わせた問題
  • 実務でよくある「セット管理」の設計問題

解答例を確認する前に、まず自分でコードを書いてみることをおすすめします。

演習1:基本操作を使って名前リストを操作しよう

以下の要件を満たすコードを書いてください。

  • 「田中」「鈴木」「佐藤」の3つの名前をArrayListに追加する
  • 先頭に「山田」を追加する
  • 「鈴木」を削除する
  • 最終的なリストの全要素を表示する

解答例:

List<String> names = new ArrayList<>();

names.add("田中");
names.add("鈴木");
names.add("佐藤");
names.add(0, "山田");
names.remove("鈴木");

for (String name : names) {
    System.out.println(name);
}

ポイントはadd(0, "山田")のようにインデックスを指定すると任意の位置に挿入できることです。remove()は要素名を直接渡せば、インデックスを調べなくても削除できますね。

演習2:1〜10のリストから偶数だけを表示しよう

1〜10の数字が入ったArrayListを作り、偶数だけをコンソールに表示するコードを書いてください。

解答例:

List<Integer> numbers = new ArrayList<>();

for (int i = 1; i <= 10; i++) {
    numbers.add(i);
}

for (int n : numbers) {
    if (n % 2 == 0) {
        System.out.println(n);
    }
}

ポイントは「リストへの追加」と「条件付きの表示」を別々のループで処理していることです。1つのループにまとめることもできますが、役割を分けて書くと読みやすいコードになりますね。

演習3:商品名と価格をセットで管理するリストを設計しよう

商品名と価格をセットで管理し、全件出力するコードを書いてください。

解答例:

List<String> names = new ArrayList<>();
List<Integer> prices = new ArrayList<>();

names.add("りんご");
names.add("バナナ");
names.add("みかん");

prices.add(120);
prices.add(80);
prices.add(100);

for (int i = 0; i < names.size(); i++) {
    System.out.println(names.get(i) + ":" + prices.get(i) + "円");
}

ポイントは「インデックスを使って2つのリストを同期させる」ことです。names.get(i)prices.get(i)は同じiで対応しているので、セットとして取り出せます。

Zetto

実務では後述するMapやクラスを使う場面も多いですがまずはこのパターンで「複数リストの対応関係」を掴んでおくといいですね。

ArrayListに関するよくある質問

ArrayListのよくある質問

よくある質問と回答をまとめました。

  • ArrayListにnullは追加できますか?
  • ArrayListはスレッドセーフですか?
  • ArrayListとHashMapはどう使い分けますか?

ArrayListにnullは追加できますか?

追加できます。ArrayListはnullを要素として許容しています。

ArrayList list = new ArrayList<>();
list.add("apple");
list.add(null);
list.add("orange");
System.out.println(list.get(1)); // null

ただし、nullが含まれている状態でメソッドを呼ぶと`NullPointerException`(ヌルポ)が発生する可能性があります。

list.get(1).length(); // NullPointerException が発生する

実務では「nullを入れない設計にする」か「nullチェックを必ず行う」のどちらかを徹底するのが基本です。意図せずnullが混入するとバグの原因になるので、注意が必要ですね。

ArrayListはスレッドセーフですか?

ArrayListはスレッドセーフではありません。

スレッドセーフとは「複数のスレッド(処理の流れ)が同時にアクセスしても安全に動作すること」を指します。

マルチスレッド環境(複数の処理が並行して動く環境)でArrayListを使うと、データが壊れる可能性があります。その場合は以下の代替手段を使います。

  • `Collections.synchronizedList()`:ArrayListを同期化する
  • `CopyOnWriteArrayList`:読み取り処理が多い場合に向いている
import java.util.Collections;
List syncList = Collections.synchronizedList(new ArrayList<>());

初心者のうちは「マルチスレッドとArrayListは相性に注意」と頭に入れておけば十分です。Web開発のバックエンドでも、Springが管理するBeanの中でArrayListを使い回す設計は避けるようにしましょう。

ArrayListとHashMapはどう使い分けますか?

ArrayListとHashMapは用途がそもそも違います。

  • ArrayList:順番のある複数のデータをリストとして管理したいとき
  • HashMap:「キーと値のペア」でデータを管理・検索したいとき
// ArrayList:名前の一覧(順番が重要)
List nameList = new ArrayList<>();
nameList.add("田中");
nameList.add("鈴木");
// HashMap:名前と年齢のペア(名前をキーに検索したい)
Map ageMap = new HashMap<>();
ageMap.put("田中", 28);
ageMap.put("鈴木", 32);
int age = ageMap.get("田中"); // 28

「番号(インデックス)でアクセスしたい」ならArrayList、「名前・IDなどのキーでアクセスしたい」ならHashMapと覚えると判断しやすいです。

JavaのArrayListを使いこなして次のステップへ

ArrayListの次のステップ

この記事では、JavaのArrayListについて基本操作から実務での設計思想まで解説しました。

重要ポイントをまとめます。

  • ArrayListとは:サイズが可変の動的リスト。配列と違い、後から要素を追加・削除できる
  • 基本操作:add・get・remove・size・containsの5つを押さえる
  • 繰り返し:for-each・通常for文・ラムダ式forEachを使い分ける
  • 実務の設計:左辺はListインターフェースで宣言するのが基本
  • 使い分け:取得・検索が多いならArrayList、追加・削除が多いならLinkedListを検討する

Java Silver・Java Goldの資格取得を目指している方にとっても、ArrayListはコレクションフレームワークの基礎として試験に頻出です。実際に僕もJava Silver・Java Goldの学習でコレクションAPIを重点的に復習しました。

まずは基本操作をひとつずつ手元で動かして、次にfor文での繰り返しを試してみてください。「動いた→なぜ動いたか言語化する」この繰り返しが、Javaの実力を着実につけていく近道です。

Java学習を続けていく中で「途中で止まってしまいそう」と感じることもあると思います。プログラミング学習で挫折しがちな原因と対策をまとめた記事もあるので、合わせて読んでみてください。

Mirai

ArrayListってこんなに奥が深かったんだね。設計の話まで出てきてびっくりした!

Zetto

Javaって文法を覚えるだけじゃなくて、設計の考え方まで身につくのが面白いところだよ。今日学んだことをひとつでも実際に書いてみると、ぐっと理解が深まるよ!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次