配列とArrayListの違い
これまで値を保管しておきたいという場合に、1つの値だけを保管したいときは変数を、1つの名前で複数の値を保管したいときは、配列を使用してきました。
例えば次のような配列があったとします。
int[] i = new int[3];
この配列には、たとえi[0]を使用しなくても必ず3つ分の領域が格納されます。
そして要素範囲外のi[3]にアクセスすると実行時エラーが発生します。
配列は一度作成されると、要素数を増やしたり減らしたりすることができません。
また配列の宣言時に格納できる型が決められるので、int型やdouble型、String型などの複数の型のデータを混在させることもできません。
そこで、Java言語では、java.utilパッケージにArrayListクラスが用意されています。
ArrayListクラスは後から要素を増やしたり、減らしたりすることができ、また様々な型のデータを格納することができます。
ただし、ArrayListクラスに格納できるのは参照型のデータだけであり、int型やdouble型といった基本データ型の値は格納することができません。
基本データ型の値を格納したい場合には、基本データ型の性質をそのまま持ったラッパークラスのオブジェクトに変換をしてから格納をします。
ポイント!コレクションフレームワーク
Javaでは複数のデータをまとめて取り扱う考え方としてコレクションフレームワーク(後述)が提供されています。
用途に応じたインターフェースやクラスが用意されており、一貫性のある管理や操作を行うことができます。
これらに定義されたメソッドを使用すると、複数のオブジェクトをまとめて格納したり、追加、削除したりすることができます。
java.util.ArrayListは、このコレクションフレームワークの中のListインターフェースに分類されるクラスの1つで、配列のようにインデックスでオブジェクトの順番を管理しており、データの重複が許されるといった特徴があります。サイズ変更可能な配列のようなものとイメージしておくとよいでしょう。
java.util.ArrayListの利用
ArrayListは、java.utilパッケージで提供されているので、このクラスを利用するには、まずimport文を使用して「java.uti.*;」もしくは「java.util.ArrayList;」と記述する必要があります。
次にArrayListクラスのインスタンス化をします。
ArrayListのインスタンス化をするとオブジェクトを格納する準備ができるので、ArrayListクラスに定義されたメソッドを使用して、ArrayListオブジェクトにデータを格納したり、削除したりすることができます。
下図はListインターフェースを実装したクラスの主なメソッドです。
【ArrayListの利用】
import java.util.ArrayList; public class ArrayList1 { public static void main(String[] args) { Integer i1 = new Integer(100); int i2 = 200; ArrayList list = new ArrayList(); list.add(i1); list.add(i2); list.add(i1); list.add(i2); for(int i = 0; i < list.size(); i++){ System.out.println(list.get(i)); } System.out.println(); list.remove(3); for(int i = 0; i < list.size(); i++){ System.out.println(list.get(i)); } } }
実行結果
100 200 100 200 100 200 100
まず1行目でjava.utilパッケージをインポートします。
4行目でIntegerオブジェクトを生成しています。
5行目では基本データ型の変数を宣言して値を格納しています。
7行目でArrayListクラスをインスタンス化しlistオブジェクトを生成します。
8行目でIntegerオブジェクトをlistオブジェクトのインデックス0にadd()メソッドを使用して格納します。
次に9行目ではint型のデータを格納しようとしています。
ArrayListに格納できるのはオブジェクトだけですが、ここではint型がautobxing機能によりInteger型に変換されて、listオブジェクトのインデックス1に格納されます。
10行目と11行目も同様です。
この時点でインデックス0から3までに4つのIntegerオブジェクトが格納されたことになります。
13行目~15行目のfor文では、size()メソッドを利用して、listオブジェクトに格納されている要素の数を調べて、要素の数分for文の繰り返し処理を行い、インデックス0から3までの値をget()メソッドを使って取り出し、出力しています。
18行目では、remove()メソッドを使って、インデックス3のオブジェクトをlistオブジェクトから削除しています。
19行目~21行目のfor文でそれぞれの要素を出力した結果、最後のインデックス3が削除されていることがわかります。
ジェネリックス
前述したようにArrayListクラスには様々なオブジェクト型を格納できます。
しかし、String型(文字列)のオブジェクトのみ格納しているArrayListオブジェクトやInteger型(数値)のオブジェクトのみ格納しているArrayListオブジェクトといったように、1つのArrayListオブジェクトに1つのクラスのオブジェクトのみ格納したい場合もあります。
このような場合には、JDK5から導入されたジェネリックスという機能を使います。
ジェネリックスを使用するには<>演算子(ダイアモンド演算子と呼びます)の中に限定したいオブジェクトの型を指定します。
例えば、
ArrayList<String> list = new ArrayList<String>();
と記述すると、Stringオブジェクトのみを格納するArrayListオブジェクトを生成できます。
String以外のオブジェクトを格納しようとするとコンパイルエラーになります。
ArrayListオブジェクト生成時に、ジェネリックスの指定は必須ではありませんが、警告が表示されます。警告はエラーではなくあくまで警告なので、そのままでも実行することは可能です。
【ジェネリックスを利用しない例】
import java.util.ArrayList; public class ArrayList2 { public static void main(String[] args) { String s1 = new String("田中"); Integer i1 = 100; ArrayList list1 = new ArrayList(); list1.add(s1); list1.add(i1); for(int i = 0; i < list1.size(); i++){ System.out.println(list1.get(i)); } } }
実行結果
田中 100
7行目のArrayListクラスのインスタンス化ではジェネリックス指定をしていないため、下図のような警告が表示されます。
これは警告なので無視することができ、4行目のString型オブジェクトと5行目のIntegerオブジェクトといった異なるオブジェクトを格納できていることがわかります。
【ジェネリックスを利用した例】
import java.util.ArrayList; public class ArrayList3 { public static void main(String[] args) { String s1 = new String("田中"); Integer i1 = 100; ArrayList<String> list1 = new ArrayList<String>(); list1.add(s1); list1.add(i1); for(int i = 0; i < list1.size(); i++){ System.out.println(list1.get(i)); } } }
7行目のArrayListクラスのインスタンス化ではジェネリックスを使用してlist1に格納できるオブジェクトをString型に限定しています。
したがって9行目のIntegerオブジェクトを格納しようとしているところでコンパイルエラーとなります。
9行目のIntegerオブジェクトを追加する部分をコメントにして、実行すると、正常に動作することがわかります。
ダイアモンド演算子
前節で説明したように<>演算子(ダイアモンド演算子)は、ArrayListなどのコレクションにオブジェクトを格納する際に格納できるオブジェクトの型を限定するものですので、左辺と右辺のデータ型を合わせる必要があります。
ArrayList<String> array1 = new ArrayList<String>(); → OK ArrayList<String> array2 = new ArrayList<Integer>(); → コンパイルエラー
しかし、これでは同じデータ型を左辺と右辺で2回記述することになり、冗長であることからJDK7から表記を簡略化して以下のように記述できるようになりました。
ArrayList<String> array3 = new ArrayList<>();
上記の記述では、右辺のデータ型指定が省略されていることがわかります。左辺の宣言時にデータ型が指定されているため、右辺では類推できると判断され、コンパイル、実行ともに可能になります。
【<>演算子】
import java.util.ArrayList; public class ArrayList4 { public static void main(String[] args) { String s1 = new String("田中"); String s2 = new String("鈴木"); String s3 = new String("佐藤"); ArrayList<String> list4 = new ArrayList<>(); list4.add(s1); list4.add(s2); list4.add(s3); for(int i = 0; i < list4.size(); i++){ System.out.println(list4.get(i)); } } }
実行結果
田中 鈴木 佐藤
8行目の記述で、右辺のデータ型が省略されていますが、コンパイル、実行ができていることがわかります。
まとめ
java.util.ArrayListクラス
- コレクションフレームワークの考え方の1つです。
- 複数のデータを格納できる仕組みです。。
- インデックス番号で管理するので、データの重複が許されます。
- ArrayListオブジェクトにデータを追加するにはadd()メソッド、削除するにはremove()メソッド、要素数を取得するにはsize()メソッド、要素を取り出すにはget()メソッドを使用します。
<>演算子(ダイアモンド演算子)
- ArrayListオブジェクトに格納する値を特定のデータ型に限定したい場合は、<>演算子を使用します。
- <>演算子を指定しないと、警告が発生するが、コンパイル、実行は可能です。
- JDK7から右辺の<>内のデータ型指定を省略できます。
独学で挫折しそうになったら、オンラインプログラミングスクール