この記事はコレクションフレームワークの紹介(概要)となります。
コレクションフレームワークを利用したプログラムの紹介は別の記事で説明します。
コレクションフレームワークに関しては、この記事とは別に3つの記事で構成します。
- List
- Set
- Map
もくじ
コレクションフレームワークとは
コレクション(集める)という用語とフレームワーク(決められた作業)という用語をつなげた用語です。
プログラムではたくさんのデータを集積および加工しますが、複数のデータを扱う際には配列があります。しかし、配列は「要素数が変更できない」「番号で管理する」等の制約があります。
そこで、配列よりも柔軟にデータを収集および利用ことができるのがコレクションクラスです。また、Javaではデータの扱い方によって、利用するクラスを使い分けることができます。
コレクションフレームワークはjava.utilパッケージに分類されます。また、データの扱い方によって「List」「Map」「Set」3つの種類に分けることができます。それぞれの特徴は以下のようになっています。
種類 | 概要 |
---|---|
List | 配列に近い構造を持っている。要素を番号で管理する。 |
Map | 要素にキー(要素を区別する値)を付けて管理する。キーの重複は不可。 |
Set | 要素に順番はなく、要素の重複を許可しない。 |
この3種類はインタフェースとして定義されており、そのインタフェースを実装するクラスがあります。クラスごとに細かく役割が分かれています。下の表は実装クラスの一部です。
Listインタフェース | |
---|---|
実装クラス | 概要 |
ArrayList | 基本的なコレクションで配列に近い構造を持っている。 |
LinkedList | 要素同士を前後双方向の関係性(リンク)を保持している。基本的に、要素の追加や削除を多用する場合にはArrayListよりも高速になる。 |
Mapインタフェース | |
---|---|
実装クラス | 概要 |
HashMap | キーのソートは行われない普遍的なマップ。 |
TreeMap | SortedMapを実装しており、キーのソートが行われる。その反面、HashMapに比べて速度が劣る。 |
Setインタフェース | |
---|---|
実装クラス | 概要 |
HashSet | 値のソートは行われない普遍的なセット。 |
TreeSet | SortedSetを実装しており、値のソートが行われる。その反面、HashSetに比べて速度が劣る。 |
コレクションフレームワークの特徴
配列と違い、コレクションフレームワークで扱うデータ(要素)の型はObjectとなります。Object型で扱うとどんな型でも格納が可能ですが、取り出す際にはキャストが必要になります。
また、本来は基本データ型は要素に利用できませんが、代わりにラッパークラスを利用することができるため疑似的に基本データ型も格納可能です。
更に、オブジェクトは同じである必要はない為、型をバラバラで登録することも可能です。しかし、キャストのエラー(ClassCastException)に注意する必要が出てくるため、総称型(ジェネリクスを利用するのが基本です。
コレクション サンプルプログラム
以下のプログラムを「Number49.java」という名前でWorkフォルダ内に保存します。
保存が完了したら、コマンドプロンプトを起動し、Number49.javaをコンパイルしてみましょう。※プログラムが長いため、必要に応じてコピペで確認してください ※このサンプルプログラムはコンパイルエラーとなります
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//コレクションはjava.utilパッケージなのでインポートが必要 import java.util.ArrayList; import java.util.Calendar; class Number49{ public static void main(String[] args){ ArrayList list = new ArrayList(); //格納するデータを用意 int a = 123; String b = "456"; Calendar c = Calendar.getInstance(); //コレクションに格納 list.add(a); //格納する型:Integer型 list.add(b); //格納する型:String型 list.add(c); //格納する型:Calendar型 //コレクションから取得 int d = list.get(0); String e = list.get(1); Calendar f = list.get(2); System.out.println(d); System.out.println(e); System.out.println(f); } } |
実行例
C:\work>javac Number49.java
Number49.java:21: エラー: 不適合な型: Objectをintに変換できません:
int d = list.get(0);
^
Number49.java:22: エラー: 不適合な型: ObjectをStringに変換できません:
String e = list.get(1);
^
Number49.java:23: エラー: 不適合な型: ObjectをCalendarに変換できません:
Calendar f = list.get(2);
^
注意:Number49.javaの操作は、未チェックまたは安全ではありません。
注意:詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください。
エラー3個
Number49.javaの補足
Number49.javaはコンパイルエラーとなります。下記の部分がエラー部分です。
String e = list.get(1);
Calendar f = list.get(2);
エラーの内容を以下に掲載します。
Number49.java:21: エラー: 不適合な型: Objectをintに変換できません:
int d = list.get(0);
^
Number49.java:22: エラー: 不適合な型: ObjectをStringに変換できません:
String e = list.get(1);
^
Number49.java:23: エラー: 不適合な型: ObjectをCalendarに変換できません:
Calendar f = list.get(2);
^
これは、総称を利用しない場合のコレクションでは内部の型はObject型となります。Object型に変換された型は元に戻す必要があり、キャストが必要です。
下記のようにキャストをすることで、元の型に戻すことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//コレクションはjava.utilパッケージなのでインポートが必要 import java.util.ArrayList; import java.util.Calendar; class Number49{ public static void main(String[] args){ ArrayList list = new ArrayList(); //格納するデータを用意 int a = 123; String b = "456"; Calendar c = Calendar.getInstance(); //コレクションに格納 list.add(a); //格納する型:Integer型 list.add(b); //格納する型:String型 list.add(c); //格納する型:Calendar型 //コレクションからキャストして取得 int d = (Integer)list.get(0); String e = (String)list.get(1); Calendar f = (Calendar)list.get(2); System.out.println(d); System.out.println(e); System.out.println(f); } } |
実行例
C:\work>javac Number49.java
注意:Number49.javaの操作は、未チェックまたは安全ではありません。
注意:詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください。
C:\work>java Number49
123
456
java.util.GregorianCalendar[time=1541566377826,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id=”GMT+09:00″,offset=32400000,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2018,MONTH=10,WEEK_OF_YEAR=45,WEEK_OF_MONTH=2,DAY_OF_MONTH=7,DAY_OF_YEAR=311,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=1,HOUR_OF_DAY=13,MINUTE=52,SECOND=57,MILLISECOND=826,ZONE_OFFSET=32400000,DST_OFFSET=0]
コンパイル時のメッセージはキャストした型が本来の型ない可能性がありますよ。実行時にエラーになる可能性がありますよ。というメッセージです。コンパイルは行われます。
コレクションで基本データ型を扱う際の注意点
コレクションに格納する際には基本データ型はラッパークラスの型に変換されて格納されます。しかし、取り出す際はObjectから基本データ型に直接変換できないため、ラッパークラスの型で取り出す必要があります。
int d = (int)list.get(0);
総称型(ジェネリクス)
コレクションに格納したデータはキャストが必要になり、キャストの型を間違ってしまう場合もあります。そこで、Java5から導入された記述法です。(この記事ではジェネリクスの詳細は割愛しています)
従来の記述 | ArrayList list = new ArrayList() ; |
---|---|
ジェネリクスを利用した記述 | ArrayList<String> list = new ArrayList<String>() ; |
ジェネリクスではクラス名に<型>を指定することで、利用する型を指定することができます。型には基本データ型は指定できませんので注意しましょう。例えば、整数や小数をArrayListへ格納する際の記述は以下のようになります。
ArrayList<Double> list_b = new ArrayList<Double>() ;
ジェネリクスを利用した場合は要素の型は固定になる為、格納できる型は制限されますが、キャストの必要がなくなります。
double yyy = list_b.get(0);
各コレクションクラスの解説ではすべてジェネリクスを利用した記述で記載します。
コレクション 復習問題
- コレクションフレームワークと関係ないインタフェースを選んでください
- 解答群
- List
- Map
- Set
- Calendar
- コレクションフレームワークの説明として誤っているものを選んでください
- 解答群
- 内部の要素はObject型になっている
- 配列と違い要素数は可変する
- 要素に基本データ型は格納できないが、ラッパークラスのオブジェクトを利用することで疑似的に可能
- java.langパッケージに属する
- Mapの説明が記載されているものを選んでください
- 解答群
- 配列のように番号で要素を管理する
- キーで要素を管理する
- 要素(値)の重複は許されていない
- スタックの構造でデータが扱える
- Setの説明が記載されているものを選んでください
- 解答群
- 配列のように番号で要素を管理する
- キーで要素を管理する
- 要素(値)の重複は許されていない
- スタックの構造でデータが扱える
- ジェネリクスを利用した記述として正しいものを選んでください
- 解答群
- ArrayList<Integer> list = new ArrayList<Integer>();
- ArrayList<int> list = new ArrayList<int>();
- ArrayList[Integer] list = new ArrayList[Integer]();
- ArrayList[int] list = new ArrayList[int]();
- お疲れ様でした。
まとめ
-
- コレクションにはList、Map、Setなどの種類がある
- java.utilパッケージにまとめられている
- 内部のデータはObject型になっている
- ジェネリクスを利用しない場合はキャストが必要
- ジェネリクスを利用した場合はキャストが必要ない
- ジェネリクスでは「クラス名<型>」で記述する