14 章: コレクション

Java では [コレクション] を [オブジェクトのグループを表すオブジェクト] とし, これらコレクションの取り扱いを統一するためのアーキテクチャとして [コレクション•フレームワーク] がある.

JDK ドキュメントでは [コレクション•フレームワーク] の利点を次のように記している:

1. プログラミングの労力の軽減
2. パフォーマンスの向上
3. 関連性のない API 間の相互運用が可能
4. API の学習に必要な労力を軽減
5. API の設計と実装に必要な労力を軽減
6. ソフトウェアの再利用を促進

ここでは, [コレクション•フレームワーク] の主要要素である次のコレクションインタフェースおよびクラスをみていく.

[コレクション•フレームワーク] のクラス構成は次のようになっている.

_images/cf2.gif

Set

[Set] は重複要素のないコレクションになる. 主な実装クラスとして次のものがる.

_images/cf-set2.gif

書式

Set 系のクラスも他のクラスと同様にインスタンスを生成し, 使用するが, [JDK 5.0] 以降からは [Generics] という機能が追加されインスタンス生成時に要素の型も宣言すうりょうになった. 例として [HashSet] の場合の書式は次のようになる:

HashSet<要素の型> 変数 = new HashSet<要素の型>();

Sample1401.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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("Dog"); // 重複する要素を追加, 大文字と小文字を区別する
	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("Dog"); // 重複要素を追加
	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("Dog"); // 重複要素を追加

	// 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);
    }
}

上記のプログラムの実行結果:

[wtopia 14]$ java Sample1401
HashSet: [null, Frog, Duck, Cat, Dog]
LinkedHashSet: [Cat, Dog, Frog, Duck, null]
TreeSet (デフォルト): [Cat, Dog, Duck, Frog]
TreeSet (降順に変更): [Frog, Duck, Dog, Cat]

List

[List] は順序付けされたコレクションになる. 主な実装クラスとして次のものがある.

_images/cf-list1.gif

書式

list 系のクラスも他のクラスと同様にインスタンスを生成し使用するが, [JDK 5.0] 以降からは [Generics] という機能が追加されインスタンス生成時に要素の型も宣言するようになった. 例として [ArrayList] の場合の書式は次のようになる:

ArrayList<要素の型> 変数 = new ArrayList<要素の型>();

Sample1402.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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 iteratorFlag){
	long startTime, endTime;
	if(iteratorFlag){
	    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";
    }
}

上記のプログラムの実行結果:

[wtopia 14]$ java Sample1402
追加処理の比較:
ArrayList = 3msec
LinkedList = 3msec
検索処理の比較:
ArrayList (for ループによる get() を使用) = 2msec
LinkedList (for ループによる get() を使用) = 360msec
ArrayList (Iterator を使用) = 3msec
LinkedList (Iterator を使用) = 2msec
更新処理の比較:
ArrayList (先頭の要素) = 409msec
LinkedList (先頭の要素) = 3msec
ArrayList (中間の要素) = 542msec
LinkedList (中間の要素) = 730msec
削除処理の比較:
ArrayList = 1299msec
LinkedList = 4msec

Map

[Map] はキーと要素をマッピングしたコレクションになる. 主な実装クラスとして次のものがある.

_images/cf-map1.gif

書式

Map 系のクラスも他のクラスと同様にインスタンスを生成し使用するが, [JDK 5.0] 以降からは [Generics] という機能が追加されインスタンス生成時に要素の型も宣言するようになった.

例として [HashMap] の場合の書式は:

HashMap<要素の型> 変数 = new HashMap<要素の>

Sample1403.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.TreeMap;

public class Sample1403{
    public static void main(String[] args){
	String[] array = {"FEIFEI", "YANGYANG", "YANGGUANG", "KANKAN"};
	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]); // HashMap
	    linkedhashmap.put(String.valueOf(i), array[i-1]); // LinkedHashMap
	    treemap.put(String.valueOf(i), array[i-1]); // TreeMap
	}

	System.out.println( "HashMap:" + hashmap.toString() );
	System.out.println( "LinkedHashMap:" + linkedhashmap.toString() );
	System.out.println( "TreeMap:" + treemap.toString() );
    }
}

上記のプログラムの実行結果:

[wtopia 14]$ java Sample1403
HashMap:{3=YANGGUANG, 2=YANGYANG, 1=FEIFEI, 4=KANKAN}
LinkedHashMap:{4=KANKAN, 3=YANGGUANG, 2=YANGYANG, 1=FEIFEI}
TreeMap:{1=FEIFEI, 2=YANGYANG, 3=YANGGUANG, 4=KANKAN}

Table Of Contents

Previous topic

13 章: パッケージ

Next topic

15 章: 標準入出力