Javaでは「コレクション」を「オブジェクトのグループを表すオブジェクト」とし、これらコレクションの取扱いを統一するためのアーキテクチャとして「コレクション・フレームワーク」があります。
JDKドキュメントでは「コレクション・フレームワーク」の利点を次のように記しています。
ここでは、「コレクション・フレームワーク」の主要要素である次のコレクションインターフェースおよびクラスをみていきます。
「コレクション・フレームワーク」のクラス構成は次のようになっています。
「Set」は重複要素の無いコレクションになります。主な実装クラスとして次のものがあります。
クラス | 特徴 |
HashSet | 「Set」の中で一番高速に処理します。要素の追加順序を保障しません。null要素を許容します。スレッドに対し同期化されません。 |
LinkedHashSet | 要素の追加順序を保障します。null要素を許容します。スレッドに対し同期化されません。 |
TreeSet | 追加された要素をソートします。ソート順序は「自然順序付け」と呼ばれる「java.lang.Comparable」インタフェースの「compare」メソッドによって定義される順序に従っています。従って、このインタフェースを実装した独自のクラスを用意し「compare」メソッドを定義することでソート順序を変更することができます。null要素を許容しません。スレッドに対し同期化されません。 |
各クラスの詳細はJDK API仕様を参照してください。
Set系のクラスも他のクラスと同様にインスタンスを生成し使用しますが、「JDK 5.0」以降からは「Generics」という機能が追加されインスタンス生成時に要素の型も宣言するようになりました。例として「HashSet」の場合の書式は次のようになります。
HashSet<要素の型> 変数 = new HashSet<要素の型>();
・サンプルソース(Sample1401.java)
import java.util.Comparator; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.TreeSet; // このクラスで「compare」メソッドを定義する為、「Comparator」インタフェースを実装しています。 public class Sample1401 implements Comparator<String> { private static String[] animal = {"Cat", "Dog", "Frog", "Duck"}; public static void main(String[] args) { testHashSet(); //「HashSet」の動作確認処理の呼び出します。 testLinkedHashSet(); //「LinkedHashSet」の動作確認処理の呼び出します。 testTreeSet(); //「TreeSet」の動作確認処理の呼び出します。 } //「HashSet」の動作確認処理 private static void testHashSet() { HashSet<String> hs = new HashSet<String>(); for(int i=0; i<animal.length; i++) { hs.add(animal[i]); } hs.add("Cat"); // 重複する要素を追加します。 hs.add(null); // nullを追加します。 System.out.println("HashSet:" + hs); } //「LinkedHashSet」の動作確認処理 private static void testLinkedHashSet() { LinkedHashSet<String> lhs = new LinkedHashSet<String>(); for(int i=0; i<animal.length; i++) { lhs.add(animal[i]); } lhs.add("Cat"); // 重複する要素を追加します。 lhs.add(null); // nullを追加します。 System.out.println("LinkedHashSet:" + lhs); } //「TreeSet」の動作確認処理 private static void testTreeSet() { TreeSet<String> ts1 = new TreeSet<String>(); // ソート順序を変更した「Comparator」クラスの実装を引数に指定します。 TreeSet<String> ts2 = new TreeSet<String>(new Sample1401()); for(int i=0; i<animal.length; i++) { ts1.add(animal[i]); ts2.add(animal[i]); } ts1.add("Cat"); // 重複する要素を追加します。 // ts1.add(null); // nullを追加すると例外(ソート時にNullPointerException)が発生します。 System.out.println("TreeSet(デフォルト):" + ts1); System.out.println("TreeSet(降順に変更):" + ts2); } //「compare」の定義(ソート順序を降順に変更) public int compare(String s1, String s2) { return s1.compareTo(s2)*-1; } }
・実行結果
C:\dev\java>javac Sample1401.java [Enter] C:\dev\java>java Sample1401 [Enter] HashSet:[Cat, null, Frog, Duck, Dog] LinkedHashSet:[Cat, Dog, Frog, Duck, null] TreeSet(デフォルト):[Cat, Dog, Duck, Frog] TreeSet(降順に変更):[Frog, Duck, Dog, Cat]
「List」は順序付けされたコレクションになります。主な実装クラスとして次のものがあります。
クラス | 特徴 |
ArryList | 「List」の中で最も基本的な実装です。nullを含む全ての要素を保障します。要素はリスト指定した位置または最後の位置に挿入することができ、挿入した位置を指定して要素を取り出すことができます。要素を配列で保持しているため要素の取得は高速に処理できますが、要素数が多くなると追加や削除処理に時間が掛かります。スレッドに対し同期化されません。 |
LinkedList | 「ArrayList」と基本操作は同じですが、「ArrayList」は要素を配列として保持しているのに対して「LinkedList」は要素をリスト構造を用いて管理しています。これにより要素の追加や削除作業が全体の要素に影響することなく行えるため高速に処理できます。しかし要素の検索はリスト構造の先端または終端から順に探していくことになるのでランダムアクセスには不向きです。このためスタックやキューのような処理に使用されます。スレッドに対し同期化されません。 |
各クラスの詳細はJDK API仕様を参照してください。
list系のクラスも他のクラスと同様にインスタンスを生成し使用しますが、「JDK 5.0」以降からは「Generics」という機能が追加されインスタンス生成時に要素の型も宣言するようになりました。例として「ArrayList」の場合の書式は次のようになります。
ArrayList<要素の型> 変数 = new ArrayList<要素の型>();
・サンプルソース(Sample1402.java)
import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; public class Sample1402 { private static int dataCount = 20000; public static void main(String[] args) { ArrayList<Integer> arraylist = new ArrayList<Integer>(); LinkedList<Integer> linkedlist = new LinkedList<Integer>(); System.out.println("追加処理の比較---------------------------------------"); System.out.println(" ArrayList = " + getAddTime(arraylist)); System.out.println(" LinkedList= " + getAddTime(linkedlist)); System.out.println("検索処理の比較---------------------------------------"); System.out.println(" ArrayList(forループによるget()を使用) = " + getGetTime(arraylist, false)); System.out.println(" LinkedList(forループによるget()を使用)= " + getGetTime(linkedlist, false)); System.out.println(" ArrayList(Iteratorを使用) = " + getGetTime(arraylist, true)); System.out.println(" LinkedList(Iteratorを使用)= " + getGetTime(linkedlist, true)); System.out.println("更新処理の比較---------------------------------------"); System.out.println(" ArrayList(先頭の要素) = " + getUpTime(arraylist, 0)); System.out.println(" LinkedList(先頭の要素)= " + getUpTime(linkedlist, 0)); System.out.println(" ArrayList(中間の要素) = " + getUpTime(arraylist, dataCount/2)); System.out.println(" LinkedList(中間の要素)= " + getUpTime(linkedlist, dataCount/2)); System.out.println("削除処理の比較---------------------------------------"); System.out.println(" ArrayList = " + getDelTime(arraylist)); System.out.println(" LinkedList= " + getDelTime(linkedlist)); } private static String getAddTime(List<Integer> list) { long startTime = System.currentTimeMillis(); for(int i=0; i<dataCount; i++) { list.add(i); } long endTime = System.currentTimeMillis(); return (endTime - startTime) + " msec"; } private static String getGetTime(List<Integer> list, boolean iteratorFlg) { long startTime,endTime; if (iteratorFlg) { startTime = System.currentTimeMillis(); for(Iterator<Integer> iterator=list.iterator();iterator.hasNext();){ iterator.next(); } endTime = System.currentTimeMillis(); }else { startTime = System.currentTimeMillis(); for(int i=0; i<dataCount; i++){ list.get(i); } endTime = System.currentTimeMillis(); } return (endTime - startTime) + " msec"; } private static String getUpTime(List<Integer> list, int index) { long startTime = System.currentTimeMillis(); for(int i=0; i<dataCount; i++) { list.add(index, i); } long endTime = System.currentTimeMillis(); return (endTime - startTime) + " msec"; } private static String getDelTime(List<Integer> list) { long startTime = System.currentTimeMillis(); while(!list.isEmpty()) { list.remove(0); } long endTime = System.currentTimeMillis(); return (endTime - startTime) + " msec"; } }
・実行結果
C:\dev\java>javac Sample1402.java [Enter] C:\dev\java>java Sample1402 [Enter] 追加処理の比較--------------------------------------- ArrayList = 16 msec LinkedList= 15 msec 検索処理の比較--------------------------------------- ArrayList(forループによるget()を使用) = 0 msec LinkedList(forループによるget()を使用)= 688 msec ArrayList(Iteratorを使用) = 0 msec LinkedList(Iteratorを使用)= 0 msec 更新処理の比較--------------------------------------- ArrayList(先頭の要素) = 812 msec LinkedList(先頭の要素)= 16 msec ArrayList(中間の要素) = 1031 msec LinkedList(中間の要素)= 1500 msec 削除処理の比較--------------------------------------- ArrayList = 2281 msec LinkedList= 0 msec
「Map」はキーと要素をマッピングしたコレクションになります。主な実装クラスとして次のものがあります。
クラス | 説明 |
HashMap | 「Map」の中で最も基本的な実装です。キー及び値にnullを使用することが出来ます。スレッドに対し同期化されません。 |
LinkedHashMap | マップに挿入したキーの順序を保障します。スレッドに対し同期化されません。 |
TreeMap | マップ内でキーを昇順にソートします。スレッドに対し同期化されません。 |
各クラスの詳細はJDK API仕様を参照してください。
Map系のクラスも他のクラスと同様にインスタンスを生成し使用しますが、「JDK 5.0」以降からは「Generics」という機能が追加されインスタンス生成時に要素の型も宣言するようになりました。例として「HashMap」の場合の書式は次のようになります。
HashMap<要素の型> 変数 = new HashMap<要素の型>();
・サンプルソース(Sample1403.java)
import java.util.HashMap; import java.util.LinkedHashMap; import java.util.TreeMap; public class Sample1403 { public static void main(String[] args) { String[] array = {"ねこ", "いぬ", "かえる", "あひる"}; HashMap<String, String> hashmap = new HashMap<String, String>(); LinkedHashMap<String, String> linkedhashmap = new LinkedHashMap<String, String>(); TreeMap<String, String> treemap = new TreeMap<String, String>(); for(int i=array.length; i>0; i--) { hashmap.put(String.valueOf(i), array[i-1]); linkedhashmap.put(String.valueOf(i), array[i-1]); treemap.put(String.valueOf(i), array[i-1]); } System.out.println("HashMap : " + hashmap.toString()); System.out.println("LinkedHashMap : " + linkedhashmap.toString()); System.out.println("TreeMap : " + treemap.toString()); } }
・実行結果
C:\dev\java>javac Sample1403.java [Enter] C:\dev\java>java Sample1403 [Enter] HashMap : {3=かえる, 2=いぬ, 4=あひる, 1=ねこ} LinkedHashMap : {4=あひる, 3=かえる, 2=いぬ, 1=ねこ} TreeMap : {1=ねこ, 2=いぬ, 3=かえる, 4=あひる}