はじめに
Javaでプログラミングをする上で、データの管理は避けて通れない道。特に、配列やリストの扱いは日常茶飯事ですよね。
しかし、初心者からすれば、どのようにうまくデータを管理するかは一筋縄ではいかない問題。
そんなあなたにピッタリなのが、Javaの「ArrayList」です。
この記事ではArrayListの作成から、データの追加、削除、更新、さらには応用テクニックまで、12の具体的な方法をサンプルコードと共に解説します。
この記事を最後まで読むと、ただの初心者からArrayListの使い手に変身できるでしょう。
●ArrayListとは
○定義と基本的な特性
ArrayListとは、Javaで提供されている動的配列の一種です。
動的配列とは、要素数が可変で、実行時にサイズを変更することができる配列のことを指します。
ArrayListはJava標準ライブラリのjava.utilパッケージに属しており、import文を使って簡単にプロジェクトに取り込むことができます。
基本的にArrayListは、内部で通常の配列を用いてデータを管理しています。
しかし、ArrayListが優れている点は、自動でサイズ調整を行ってくれる点です。
つまり、配列のように事前にサイズを指定する必要がないのです。
○なぜArrayListを使うのか
初心者から上級者まで多くのJavaプログラマがArrayListを使う理由はいくつかあります。
第一に、前述の通りArrayListはサイズが動的に変更できるため、データの追加や削除が非常に容易です。
また、ArrayListは様々な便利なメソッドが豊富に用意されています。
例えば、特定の位置にデータを挿入したり、複数のArrayListを結合したりといった高度な操作も簡単に行えます。
さらに、ArrayListはGenerics(ジェネリクス)に対応しているため、任意の型(クラス)のオブジェクトを格納することができます。
これにより、型安全なコードを書くことが可能となり、バグの発生リスクを減らすことができます。
●ArrayListの作り方
○インスタンスの作成
ArrayListの使用を開始するための第一歩は、ArrayListのインスタンス(実体)を生成することです。
Javaでは「new」キーワードを使ってこれを行います。
基本的な構文は次のようになります。
このコードはJavaのArrayListクラスから新しいオブジェクトを生成し、そのオブジェクトをmyArrayList
という名前で参照しています。
また、このArrayListはString型の要素を保持することが指定されています。
○イニシャライザを使った初期化
ArrayListは生成と同時に初期データを設定することも可能です。
これをイニシャライザと呼びます。イニシャライザを使用すると、次のようなコードでArrayListを作成できます。
この例では、”Apple”、”Banana”、”Cherry”という三つのString要素でArrayListを初期化しています。
Arrays.asList()
メソッドを用いて、固定長のリストを作成し、それをArrayListのコンストラクタに渡しています。
□サンプルコード1:基本的なArrayListの作成
さて、ここでは具体的なコードを通じて、ArrayListの作成方法を総合的に見てみましょう。
このコードを実行すると、次の出力が得られます。
このように、numbers
は空のArrayListとして生成され、fruits
は”Apple”、”Banana”、”Cherry”で初期化されたArrayListとなります。
●ArrayListに要素を追加する方法
ArrayListが生成された後、次は要素をどのように追加するかというテーマ性があります。
具体的な操作に移る前に、主に使用されるメソッドには二つがあります。
○addメソッド
add
メソッドは、ArrayListに新しい要素を追加する基本的な方法です。
このメソッドを用いることで、ArrayListの最後に要素を追加できます。
このコードでは、まずanimals
という名前で空のArrayListを生成しています。
その後、add
メソッドを使って”Dog”と”Cat”という要素を追加しています。
コード実行後、コンソールには[Dog, Cat]
と表示されます。
○addAllメソッド
addAll
メソッドは、複数の要素をまとめてArrayListに追加するために使用されます。
このメソッドを使えば、別のCollectionオブジェクト(例えば、ListやSetなど)のすべての要素をArrayListに追加することができます。
このコードを実行すると、コンソールには[Dog, Cat, Elephant, Lion]
と表示される結果が得られます。
それはnewAnimals
の全ての要素がanimals
に追加されているからです。
□サンプルコード2:要素の追加
実際のプログラムでは、単一の要素を追加する場合もあれば、複数の要素を一度に追加する場合もあります。
こちらはその両方のケースを網羅した例です。
このサンプルコードを実行すると、最初に単一要素追加後: [Apple]
、次に複数要素追加後: [Apple, Banana, Cherry]
と表示されます。
これにより、add
メソッドは単一の要素を、addAll
メソッドは複数の要素をArrayListに追加できることが確認できます。
●ArrayListから要素を削除する方法
ArrayListに要素を追加した後、次なるステップは要素の削除です。
いくらでも要素を追加できるものの、そのままではデータの管理が難しくなる場合もあります。
ここでは、ArrayListから要素を削除する際に使用される主要なメソッドを2つ紹介します。
○removeメソッド
remove
メソッドは、特定の要素またはインデックスに基づいて要素を削除します。
このメソッドを使用すると、指定した要素がArrayListから取り除かれます。
このコードでは、「Dog」、「Cat」、「Elephant」という3つの要素を含むArrayListを生成しています。
そして、remove
メソッドを用いて「Cat」という要素を削除しています。
このコードの実行によって出力される結果は[Dog, Elephant]
です。
○removeAllメソッド
removeAll
メソッドは、複数の要素を一度に削除するためのメソッドです。
引数として別のコレクションを指定すると、そのコレクションに含まれる要素がすべて削除されます。
このサンプルコードでは、「Dog」、「Cat」、「Elephant」、「Lion」という4つの要素が含まれるArrayListから、「Dog」と「Lion」を一度に削除しています。
このコードを実行すると、出力される結果は[Cat, Elephant]
です。
□サンプルコード3:要素の削除
要素の削除においても単一と複数、両方のケースが考えられます。
下記のサンプルコードは、その両方のケースをカバーしています。
このサンプルコードを実行すると、「単一要素削除後: [Banana]」と「複数要素削除後: [Cherry]」が出力されます。
これにより、remove
メソッドが単一の要素を、removeAll
メソッドが複数の要素を効率よく削除できることが確認できます。
●ArrayListの要素を読み取る方法
要素の追加や削除ができるようになったら、次に必要なスキルはArrayList内の要素の読み取りです。
要素を読み取るためにはいくつかの方法がありますが、ここでは主にget
メソッドとiterator
を用いた走査について詳しく説明します。
○getメソッド
JavaのArrayListではget
メソッドを用いて特定のインデックスに位置する要素を読み取ることができます。
get
メソッドは指定したインデックスの要素を戻り値として返します。
上記のコードでは、fruits
という名前のArrayListに「Apple」と「Banana」を追加しています。
その後、get
メソッドを使用してインデックス0(最初)の要素を読み取っています。
このコードを実行すると、コンソールに「取得した要素: Apple」と表示されます。
○iteratorを使った走査
複数の要素を順番に読み取る場合、iterator
を使用する方法もあります。
iterator
はJavaのコレクションフレームワークで提供されているインターフェースで、ArrayListを含む多くのコレクションクラスで利用可能です。
このコードでは、最初に「Apple」と「Banana」を含むArrayListを作成しています。
次に、そのArrayListからiterator
オブジェクトを取得し、そのiterator
を使って要素を順に読み取っています。
このコードを実行すると、コンソールに「取得した要素: Apple」と「取得した要素: Banana」と表示されます。
□サンプルコード4:要素の読み取り
以上の2つの方法を組み合わせた下記のコードでは、get
メソッドとiterator
を用いて同じArrayListから要素を読み取っています。
このコードを実行すると、コンソールに「getメソッドで取得した要素: Apple」と「iteratorで取得した要素: Apple Banana」と表示されます。
このように、要素の読み取り方は目的や状況に応じて最適な方法を選ぶことができます。
get
メソッドは特定の要素に瞬時にアクセスする際に便利ですが、要素を順番に処理する場合はiterator
が一般的に使用されます。
●ArrayListの要素を更新する方法
ArrayListでのデータ管理においては、要素の更新もよく行われる操作です。
特定のインデックスにある要素を新しい値で上書きするケースが多いでしょう。
要素を更新する主な手段としてはset
メソッドがあります。
○setメソッド
set
メソッドは、指定されたインデックスの位置にある要素を新しい要素で置き換えます。
このメソッドは元の要素を新しい要素で上書きするため、元の要素は失われます。
上記のサンプルコードでは、最初に”Apple”と”Banana”が格納されたArrayListを作成しています。
次にset
メソッドを用いて、インデックス0の位置にある”Apple”を”Cherry”で上書きしています。
このコードを実行すると、コンソールに更新後のArrayList: [Cherry, Banana]
と表示されます。
□サンプルコード5:要素の更新
set
メソッド以外にも、インデックスを指定して既存の要素を更新する方法がいくつかあります。
例えば、remove
メソッドとadd
メソッドを組み合わせることもできます。
このコードでは、最初にインデックス0の”Apple”をremove
メソッドで削除しています。
その後、add
メソッドでインデックス0に新しい要素”Cherry”を挿入しています。
この場合も、コードを実行すると、コンソールに別の方法で更新後のArrayList: [Cherry, Banana]
と表示されます。
このようにset
メソッドは直感的で簡単に要素を更新できますが、元の要素の位置関係を保ちつつ新しい要素を挿入したい場合には、remove
とadd
の組み合わせも有効です。
●ArrayListをソートする方法
リスト内の要素を特定の順序で並び替える、いわゆるソート操作は、データ処理で非常によく使われます。
JavaのArrayListも例外ではなく、特定のメソッドやクラスを使用して簡単にソートできます。
○Collections.sortメソッド
Javaの標準ライブラリに含まれるCollections
クラスのsort
メソッドは、リスト型のデータを破壊的にソートします。
破壊的とは、元のリストのデータ自体が変更されることを意味します。
このsort
メソッドは、特にパラメータが与えられない場合、自然順序付けに基づいてソートを行います。
上記のコードでは、ArrayList<Integer>
型のnumbers
リストを作成し、その中に30、10、20という3つの要素を追加しています。
その後、Collections.sort
メソッドを使用して、このリストをソートしています。
ソートが完了すると、リストnumbers
は[10, 20, 30]という順番になります。
□サンプルコード6:ArrayListのソート
自然順序付け以外にも、独自の比較ルールに基づいてソートを行いたい場合もあります。
その際には、Comparator
インターフェースを実装したクラスを作成し、そのインスタンスをCollections.sort
メソッドの第二引数として渡します。
このコードでは、descComparator
という名前でComparator<Integer>
型の匿名クラスを作成しています。
compare
メソッド内で降順にソートするための比較処理を実装しています。
このdescComparator
をCollections.sort
メソッドの第二引数として渡すことで、numbers
リストは降順、すなわち[30, 20, 10]という順番にソートされます。
●ArrayListのサイズを確認する方法
プログラミングでデータを扱う際、データ構造のサイズを確認することは一般的な要件と言えます。
JavaでのArrayListにおいても、そのサイズを知ることは多くの場合において役立ちます。
具体的な使用ケースとしては、ループ処理でArrayListのすべての要素にアクセスする際や、ArrayListに新しい要素を追加する前に現在の容量を確認するなどがあります。
○sizeメソッド
ArrayListのサイズを確認する最も直接的な方法はsize
メソッドを使用することです。
このメソッドはArrayListの要素数を返すため、リストが空であれば0を返します。
ここで一つのサンプルコードを見てみましょう。
このコードでは、ArrayList<String>
型のfruits
という名前のリストを作成しています。
このリストには”Apple”、”Banana”、”Cherry”という3つの文字列要素が追加されています。
size
メソッドを用いてArrayListのサイズを取得し、その値をsize
変数に格納しています。
最後にそのサイズを出力しています。
このコードを実行すると、コンソールにはArrayListのサイズ: 3
と表示されます。
□サンプルコード7:ArrayListのサイズ確認
サイズが0であるかどうかを確認することで、ArrayListが空であるかどうかも判定できます。
そのようなケースを考慮に入れたサンプルコードを紹介します。
このコードを実行すると、「ArrayListは空です。」というメッセージが出力されます。
なぜなら、fruits
リストには何も追加されていないため、そのサイズは0になるからです。
●ArrayListの応用例
JavaにおけるArrayListは多用されるデータ構造であり、その用途は基本的なリスト操作から高度なデータ処理まで多岐にわたります。
それでは、ArrayListの応用例としてデータフィルタリング、データ集計、そしてStream APIとの連携について説明します。
○ArrayListを使ったデータのフィルタリング
特定の条件に合致する要素だけを取り出す場合、ArrayListは非常に役立ちます。
具体的な方法としては、for-eachループやIteratorを使って元のArrayListから条件に合致する要素だけを新しいArrayListに格納するという手法があります。
□サンプルコード8:データフィルタリング
このコードでは1から10までの整数を含むArrayListを作成しています。
その後、偶数のみを格納する新しいArrayList(evenNumbers
)を作成しています。
この新しいリストには、元のnumbers
リストから偶数だけが格納されます。
コードを実行すると、[2, 4, 6, 8, 10]というArrayListが出力されます。
○ArrayListを使ったデータの集計
次に、ArrayList内のデータを集計する例について説明します。
例えば、Integer型のArrayListがある場合、その要素の合計や平均を求めることができます。
□サンプルコード9:データ集計
このサンプルコードでは、ArrayListに格納されている数値(この場合は試験の点数)を合計して平均を出しています。
このようにしてscores
から合計点と平均点を計算することができます。
コードを実行すると、”合計点: 347″と”平均点: 86.75″が出力されます。
○ArrayListとStream API
Java 8以降、Stream APIを用いると、ArrayListの操作が一層効率的になります。
特に、フィルタリングや集計において便利な機能が多数提供されています。
□サンプルコード10:Stream APIとの連携
このコードは、最初に1から10までの整数が格納されたArrayListを作成します。
その後、Stream APIを使用して偶数だけを取り出し、新しいリストに格納しています。
最後に、その新しいリストを出力しています。
実行結果として[2, 4, 6, 8, 10]というArrayListが出力されます。
●注意点と対処法
ArrayListは便利である一方で、注意が必要な点もあります。
それでは、特に注意すべき2点、null要素の取り扱いとスレッドセーフについて詳しく説明します。
○null要素の取り扱い
ArrayListはnull要素を許容するため、操作を行う際にNullPointerExceptionを引き起こす可能性があります。
例えば、getメソッドでnullを取得し、その後でその要素のメソッドを呼び出すと、NullPointerExceptionが発生します。
このような問題を防ぐ一つの方法は、要素を操作する前にnullチェックを行うことです。
このコードでは、ArrayListに”apple”、null、”orange”という3つの要素を追加しています。
そして、各要素に対してnullチェックを行った後で、大文字に変換して出力しています。
この結果、「APPLE」、「この要素はnullです。」、「ORANGE」という出力が得られます。
○スレッドセーフについて
基本的なArrayListはスレッドセーフではありません。
そのため、複数のスレッドから同時にArrayListにアクセスする場面では問題が生じる可能性があります。
これを解決するためには、CollectionsクラスのsynchronizedListメソッドを用いてスレッドセーフなリストを生成することが一般的です。
□サンプルコード11:スレッドセーフなArrayListの作成
このコードでは、まず通常のArrayListを作成しています。
その後、CollectionsクラスのsynchronizedListメソッドを用いて、スレッドセーフなArrayListを生成しています。
このArrayListに新しい要素を追加したり、その内容を出力する際には、synchronizedブロックを用いて排他制御を行っています。
実行すると、”apple”、”banana”、”cherry”、”date”が順に出力されます。
●カスタマイズ方法
ArrayListを一歩進めて使うためには、カスタムクラスを要素とする方法があります。
基本型やJavaが提供するクラスだけでなく、自分で定義したクラスをArrayListの要素として使用することで、より複雑なデータ構造を簡単に扱うことができます。
○カスタムクラスを要素とするArrayList
Javaでオブジェクト指向プログラミングを行う際、自分自身でクラスを定義して、そのインスタンスをArrayListで管理するケースは多いです。
たとえば、”Person”というクラスがあり、その属性(名前、年齢など)をArrayListで一括管理したい場合、カスタムクラスを要素とするArrayListを使います。
□サンプルコード12:カスタムクラスを使ったArrayList
このサンプルコードでは、まず「Person」という名前のカスタムクラスを定義しています。
このクラスには「name」と「age」という二つのフィールドがあります。
そして、その後でこの「Person」クラスのオブジェクトを要素とするArrayList(personList)を作成しています。
このArrayListには、Alice(30歳)、Bob(40歳)、Charlie(50歳)の3つのPersonオブジェクトを追加しています。
最後に、ArrayList内の各要素(Personオブジェクト)を出力しています。
このプログラムを実行すると、次のようにコンソールに表示されます。
まとめ
JavaのArrayListは、動的な配列を扱う際に非常に便利なデータ構造です。
この記事で取り上げた要点は、ArrayListの使い方の基本から、要素の追加、削除、更新、そして読み取り方法、さらにはソートやサイズ確認まで多岐にわたります。
この記事が、あなたのプログラミング学習や仕事における具体的な課題解決に少しでも貢献できれば幸いです。
今後も、より高度なプログラミングテクニックをマスターするための学習を続けましょう。