JavaにおけるArrayListとは?
ArrayListは、可変長の配列を実現するクラスです。通常の配列は、作成時にサイズを固定してしまいますが、ArrayListには必要に応じて自動的に大きさが変わる特別な仕組みがあります。
例えば、生徒名簿を管理するとき通常の配列では30人分の枠を用意しても、転校生が来ると足りなくなります。反対に20人分の枠を用意しても、実際の人数が15人だと無駄が生じます。ArrayListなら生徒が増えても減っても、ちょうど必要な分だけの大きさに自動調整してくれるのです。
ArrayListは「java.util」パッケージに含まれていて、次のような特徴があります。
- 整数や小数などの基本型(プリミティブ型)を直接は格納できず、オブジェクトのみを格納できる
- 「ラッパークラス」(Integer, Double, Booleanなど)を使えば基本型の値も格納できる
- 配列と同じようにインデックス(0から始まる番号)で各要素にアクセスできる
- 重複した値を複数入れても問題ない
- 格納されたデータの順番を覚えている
ArrayListは内部的には普通の配列を使っていますが、容量が足りなくなると、より大きな配列を新しく作り、データをコピーするという賢い仕組みになっています。このため、ArrayListを使うとサイズの管理を気にする必要がありません。
基本構文
ArrayListの使い方は難しくありません。使うためには、まず「java.util.ArrayList」をインポートする必要があります。基本的なコード例を見てみましょう。
大事なのは <String> のような書き方です。
これを「ジェネリクス」と呼び、どんな種類のデータをこのリストに入れるかを指定します。
例えば、
- ArrayList<String>:文字列だけを格納できるリスト
- ArrayList<Integer>:整数(の参照型)だけを格納できるリスト
- ArrayList<Double>:小数(の参照型)だけを格納できるリスト
などがあります。
ジェネリクスを使うメリットは、間違った型のデータが入らないようにコンパイル時にチェックしてくれることです。具体的には、文字列用のリストに数値を入れようとすると、コンパイルエラーになるため、実行前にミスに気付けます。
このように、ArrayListは型安全性を確保しながら、可変長のデータ構造を提供してくれる親切な配列なのです。
実用例
実際の例を通して、ArrayListの使い方をマスターしていきましょう。
ここからは動物の名前を使った具体例で、初心者でも理解しやすいように説明します。コードとその実行結果をセットで示しているので、動作がイメージしやすくなっていますが、実践してみるとさらに理解が深まるでしょう。
ArrayListの作成と初期化
空のリストから作成する方法と、初期値をあらかじめ設定する2つの方法があります。空のArrayListを作成し、そこに要素を追加する方法を見てみましょう。
出力結果:
[ライオン, トラ, クマ]
このように、new ArrayList<>()で空のリストを作成し、add()メソッドで要素を追加していきます。最後にSystem.out.println()でリスト全体を表示すると、自動的に見やすい形式で出力されます。
要素の追加(add)
ArrayListに要素を追加するには、主に2つの方法があります。末尾に追加する方法と、指定位置に追加する方法です。
ペットの名前をリストに追加する例で見てみましょう。
出力結果:
2つ追加後: [イヌ, ネコ]
位置指定追加後: [イヌ, ウサギ, ネコ]
この例から分かるように、add(要素) メソッドはリストの末尾に要素を追加します。一方、add(インデックス, 要素) メソッドを使うと、指定した位置に要素を挿入できます。上のケースでは、インデックス1(2番目の位置)に「ウサギ」を挿入しています。これにより、「イヌ」と「ネコ」の間に「ウサギ」が入ります。
ちなみに、範囲外のインデックスを指定すると(例えば、5要素しかないリストで10番目に追加しようとした場合)、IndexOutOfBoundsExceptionというエラーが発生します。
要素の取得(get)
ArrayListから要素を取得するには、インデックス(位置)を指定します。インデックスは0から始まるので、最初の要素は0番目、2番目の要素は1番目というように指定します。
鳥の名前のリストから特定の鳥を取得してみましょう。
出力結果:
リスト全体: [スズメ, カラス, ハト]
最初の鳥: スズメ
2番目の鳥: カラス
get(インデックス)メソッドは、指定した位置にある要素を返します。この例では、最初の要素である「スズメ」と、2つ目の要素である「カラス」を取得しています。存在しないインデックスを指定すると、IndexOutOfBoundsExceptionというエラーが発生します。
要素の削除(remove)
ArrayListから要素を削除するには、2つの方法があります。インデックスを指定する方法とオブジェクト自体を指定する方法です。
昆虫のリストから要素を削除してみましょう。
出力結果:
元のリスト: [クモ, カブトムシ, バッタ]
インデックス1削除後: [クモ, バッタ]
クモ削除後: [バッタ]
removeインデックス) メソッドは、指定した位置の要素を削除します。上の例では、インデックス1の「カブトムシ」を削除しています。
remove(オブジェクト) メソッドは、指定したオブジェクトと一致する最初の要素を削除します。この例では「クモ」を削除しています。
削除すると、その後ろにある要素が自動的に前にずれるので、隙間ができることはありません。つまり、リストは常に連続した要素を持ちます。もし、存在しないインデックスを指定するとIndexOutOfBoundsException というエラーが発生します。オブジェクトを指定して削除する場合、そのオブジェクトがリストに存在しなければ何も起こらず(エラーにはならず)、リストはそのままの状態が維持されます。
要素の検索(contains/indexOf)
ArrayListで特定の要素を検索する方法は、主に2つあります。要素が含まれているかをチェックする方法と、要素の位置(インデックス)を調べる方法です。
出力結果:
リスト: [サメ, クジラ, イルカ]
サメは含まれる?: true
カメは含まれる?: false
イルカの位置: 2
contains(オブジェクト) メソッドは、指定した要素がリストに含まれているかどうかをチェックし、含まれていれば true、含まれていなければ false を返します。この例では「サメ」は含まれているので true、「カメ」は含まれていないので false になります。
indexOf(オブジェクト) メソッドは、指定した要素がリスト内のどの位置にあるかを返します。最初に見つかった位置のインデックスが返されます。この例では「イルカ」は3番目(インデックスでは2)にあるので、2が返されます。もし要素が見つからない場合は、-1が返されます。
ArrayListのサイズと空チェック
ArrayListの要素数を確認したり、リストが空かどうかを調べたりする方法は非常に簡単です。
畜産動物の例で確認してみましょう。
出力結果:
リストは空?: true
追加後のリスト: [ウシ, ブタ]
要素数: 2
リストは空?: false
isEmpty() メソッドは、リストが空かどうかを調べます。空の場合は true、要素が1つでもあれば false を返します。最初は空のリストなので true が返されますが、要素を追加した後は false になります。
size() メソッドは、リスト内の要素数を返します。この例では2つの要素を追加したので、サイズは2になります。
このようなメソッドは、リストを処理する前に状態を確認するのに便利です。
拡張for文によるArrayListの操作
ArrayListの要素をすべて処理する方法として、拡張for文(拡張for-each文)があります。特に、インデックスが不要な場合には簡潔でわかりやすいコードが書けます。
哺乳類のリストを順に表示してみましょう。
出力結果:
哺乳類リスト: [ゾウ, キリン, サル]
各要素を表示:
- ゾウ
- キリン
- サル
拡張for文は for (型 変数名 : コレクション) という形式で書きます。この例では for (String animal : mammals) と書いて、mammalsリストの各要素をanimal変数に順番に代入しながら繰り返しています。通常のfor文(for (int i = 0; i < mammals.size(); i++))と比べて、次のようなメリットがあります。
- コードが短くシンプル
- インデックスのミスによるバグが発生しない
- 読みやすく、意図が明確になる
特に単純に全要素に対して同じ処理をする場合は、拡張for文を使うとコードがすっきりします。ただし、処理中に要素を削除したり、インデックスそのものが必要な場合は、通常のfor文を使う必要があるのでその点は認識しておきましょう。
まとめ
Java ArrayListは、プログラミングの可能性を大きく広げる便利なツールです。
今回学んだことを振り返ってみましょう。
- ArrayListは、データの追加に応じて自動的にサイズが拡張される
- ArrayListの基本的な作成方法と初期化
- 要素の追加、取得、削除、検索のやり方
- 配列のサイズの確認と空かどうかのチェック
- Collections.sortを使ったデータの並べ替え
- 拡張for文を使った処理
応用的な話をすると、ArrayListはJavaのコレクションフレームワークの一部として、他のデータ構造(LinkedList、HashSet、HashMapなど)と一緒に使うことができます。状況や目的に応じて最適なデータ構造を選べるようになると、より効率的なプログラムを書くことができるようになるでしょう。
また、実際のプログラム開発ではリスト処理は非常によく使われています。例えば、データベースから取得した結果の管理、ユーザー入力の保存、動的に変化するデータの操作など、様々な場面でArrayListは活躍するのです。
ぜひ、この記事で学んだ知識を活かして、より効率的なJavaプログラムを作成できるようになりましょう。