Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。

List

このページではコレクション・フレームワークの内、Listインタフェースについて説明します。

Listの概要

Listインタフェースは重複要素を許可し、要素において順番を持ちます。インデックス番号により要素にアクセスするメソッドや、要素のインデックス番号を調べるメソッドが用意されています。Listインタフェースを実装するクラスとして、ArrayList、LinkedListが定義されています。

ArrayListクラス

Listインタフェースを実装する基本となるクラスです。ランダムアクセスをサポートしており、要素の検索において高速に動作します。要素の追加、削除においては追加、削除された要素以降の要素を再配置する必要があるため低速です。

ArrayListクラスはVectorクラスの後継として定義されたものです。違いは要素の操作を行う際、Vectorクラスが同期化されているのに対して、ArrayListクラスが同期化されていない点です。ArrayListクラスは同期化されていない分、高速に動作します。同期化された処理をArrayListクラスで行う場合は、ArrayListクラスに同期処理を実装します。

LinkedListクラス
要素の順番を各要素の前後のリンク情報を持つことによって保持します。要素の追加、削除を行う場合、リンク情報を変更することによって処理するため高速に動作します。 要素の検索においては、要素に順番にアクセスするため低速です。

【例1】 要素を先頭から追加する場合、要素を最後から追加する場合、要素を検索する場合においてArrayListクラスとLinkeListクラスの実行速度を比較します。

import java.util.*;

public class ExCollection2 {
    public static void main(String[] args) {
        long start, stop;
        ExCollection2 exObject = new ExCollection2();
        List al1 = new ArrayList();
        List ll1 = new LinkedList();
        List al2 = new ArrayList();
        List ll2 = new LinkedList();

        //ArrayList先頭追加処理
        start = System.currentTimeMillis();  //(1)現在時刻を取得
        exObject.addhead(al1);  //(2)addheadメソッド呼び出し
        stop = System.currentTimeMillis();  //(4)現在時刻を取得
        //(5)処理時間を表示
        System.out.println("ArrayListの先頭追加処理---" + (stop-start));

        //LinkedList先頭追加処理
        start = System.currentTimeMillis();
        exObject.addhead(ll1);
        stop = System.currentTimeMillis();
        System.out.println("LinkedListの先頭追加処理---" + (stop-start));

        //ArrayList最後追加処理
        start = System.currentTimeMillis();
        exObject.addend(al2);
        stop = System.currentTimeMillis();
        System.out.println("ArrayListの最後追加処理---" + (stop-start));

        //LinkedList最後追加処理
        start = System.currentTimeMillis();
        exObject.addend(ll2);
        stop = System.currentTimeMillis();
        System.out.println("LinkedListの最後追加処理---" + (stop-start));

        //ArrayList検索処理
        start = System.currentTimeMillis();
        exObject.select(al1);
        stop = System.currentTimeMillis();
        System.out.println("ArrayListの検索処理---" + (stop-start));

        //LinkedList検索処理
        start = System.currentTimeMillis();
        exObject.select(ll1);
        stop = System.currentTimeMillis();
        System.out.println("LinkedListの検索処理---" + (stop-start));
    }

    //(3)先頭追加処理
    void addhead(List exList) {
        for (int i = 0; i < 10000; i++) {
            exList.add(0, new Integer(i));
        }
    }

    //(6)最後追加処理
    void addend(List exList) {
        for (int i = 0; i < 10000; i++) {
            exList.add(new Integer(i));
        }
    }

    //(7)検索処理
    void select(List exList) {
        for (int i = 0; i < exList.size(); i++) {
            exList.get(i);
        }
    }
}

解説1

  1. (1)currentTimeMillisメソッドを使用し、現在時刻を取得します。
  2. (2)コレクションの先頭から要素を追加していくメソッドaddheadを呼び出します。
  3. (3)addheadメソッドにより先頭から要素を追加していきます。addheadメソッドの引数をList型変数にしているのがポイントです。これにより、Listインタフェースを実装しているArrayListオブジェクトも、LinkedListオブジェクトも引数に値を代入することができます。
  4. (4)currentTimeMillisメソッドを使用し、現在時刻を取得します。
  5. (5)addheadメソッドの処理で経過した時刻を表示します。
    ※ 以降、同様にLinkedListクラスの先頭追加処理、ArrayListクラスの最後追加処理と実行していきます。
  6. (6)addendメソッドにより、最後追加処理を行います。addメソッドをインデックス番号を指定せずに実行するとコレクションの最後から要素を追加します。
  7. (7)selectメソッドにより、検索処理を行います。getメソッドにより指定したインデックス番号の要素にアクセスします。

実行結果1

D:\JAVA>javac ExCollection2.java

D:\JAVA>java ExCollection2
ArrayListの先頭追加処理---1021  # 先頭から要素を追加する場合極端に
LinkedListの先頭追加処理---40   # ArrayListの処理速度が落ちます。

ArrayListの最後追加処理---60   # 最後から要素を追加する場合、
LinkedListの最後追加処理---50   # それほど処理速度は変わりません。

ArrayListの検索処理---20     # LinkedListはランダムアクセスをサポート
LinkedListの検索処理---1773    # していないため、処理速度が落ちます。

D:\JAVA>

Listのコンストラクタ

ArrayListクラスのコンストラクタ

コンストラクタ 説明
ArrayList( ) 初期容量10の空のArrayListを作成します。
ArrayList(Collection) 引数に指定されたコレクションの要素を保持したArrayListを作成します。
ArrayList(int) 引数に指定した容量の空のArrayListを作成します。

LinkedListクラスのコンストラクタ

コンストラクタ 説明
LinkedList( ) 空のLinkedListを作成します。
LinkedList(Collection) 引数に指定されたコレクションの要素を保持したLinkedListを作成します。

※ ArrayListのコンストラクタを使用する場合、要素の含まれる容量がわかっている場合は初期容量を指定してリストを作成します。初期容量を越える要素が追加される場合は、現容量の50%の容量を拡大します。この処理は非常に負荷を高める処理です。

【例2】引数にコレクションを指定して、リストを作成する例です。

import java.util.*;

public class ExCollection3 {
    public static void main(String[] args) {
        Set hs1 = new HashSet();  //(1)HashSetオブジェクトの生成
        for (int i = 0; i < 10; i++) {
            hs1.add(new Integer(i));  //(2)要素の追加
        }

        System.out.println("HashSetの要素" + hs1);  //(3)要素の表示

        //(4)hs1オブジェクトの要素を保持したArrayListオブジェクトの生成
        List al1 = new ArrayList(hs1);
        System.out.println("ArrayListの要素" + al1);  //(5)要素の表示
    }
}

解説2

  1. (1)HashSetオブジェクトhs1を生成します。
  2. (2)hs1オブジェクトに0から9までの要素を追加します。
  3. (3)hs1オブジェクトの要素を表示します。
  4. (4)ArrayListのコンストラクタの引数にhs1オブジェクトを指定し、hs1オブジェクトの要素を保持したArrayListオブジェクトal1を生成します。hs1オブジェクトはCollectionインタフェースを継承したSetインタフェースを実装したオブジェクトであるため、引数に指定できます。
  5. (5)al1オブジェクトの要素を表示します。

実行結果2

D:\JAVA>javac ExCollection3.java

D:\JAVA>java ExCollection3
HashSetの要素[2, 4, 8, 9, 6, 1, 3, 7, 10, 5]
ArrayListの要素[2, 4, 8, 9, 6, 1, 3, 7, 10, 5]
# ArrayListの要素とHashSetの要素が同じであり、al1オブジェクトがhs1オブジェクトの要素を保持していることがわかる。

D:\JAVA>

Listのメソッド

ArrayListクラス、LinkedListクラス双方で定義されている主要なメソッドを紹介します。各クラスのメソッドの詳細は、APIリファレンスを参照してください。

戻り型 メソッド 説明
void add(int, Object) 引数intで指定された位置に、要素を追加します。
boolean add(Object) リストの最後に要素を追加します。
boolean addAll(Collection) リストの最後に、引数Collectionで指定された要素すべてを追加します。
boolean addAll(int, Collection) 引数intで指定された位置に、引数Collectionで指定された要素すべてを追加します。
void clear( ) リストからすべての要素を削除します。
Object get(int) リスト内のインデックス番号で指定された位置にある要素を返します。
Object remove(int) リスト内のインデックス番号で指定された位置にある要素を削除します。返り値として、削除された要素を返します。
Object set(int, Object) リスト内のインデックス番号で指定された位置にある要素を引数Objectで指定された要素に置き換えます。返り値として、置き換えられた古い要素を返します。
int size( ) リスト内にある要素の数を返します。

【例3】代表的なメソッドを使用して、リスト内の要素を操作する例です。

import java.util.*;

public class ExCollection4 {
    public static void main(String[] args) {
        String[] s1_array = {"R", "O", "A", "D"};
        String[] s2_array = {"J", "A", "V", "A"};
        List ll1 = new LinkedList();

        //(1)addメソッドにより、要素を追加
        for (int i = 0; i < s1_array.length; i++) {
            ll1.add(s1_array[i]);
        }
        System.out.println("add処理" + ll1);  //(2)

        //(3)addAllメソッドにより、全要素を追加
        ll1.addAll(ll1);
        System.out.println("addAll処理" + ll1);  //(4)

        //(5)setメソッドにより、要素を置換え
        for (int i = 0; i < s2_array.length; i++) {
            ll1.set(i, s2_array[i]);
        }
        System.out.println("set処理" + ll1);  //(6)

        //(7)clearメソッドにより、要素を削除
        ll1.clear();
        System.out.println("clear処理" + ll1);  //(8)
    }
}

解説3

  1. (1)addメソッドを使用し、LinkedListオブジェクトll1に配列s1_arrayの要素を追加します。
  2. (2)ll1オブジェクトの要素を表示します。
  3. (3)addAllメソッドを使用し、LinkedListオブジェクトll1にll1の要素すべてを追加します。
  4. (4)ll1オブジェクトの要素を表示します。
  5. (5)setメソッドを使用し、ll1オブジェクトのインデックス番号0~4の要素を、配列s2_arrayの要素で置き換えます。
  6. (6)ll1オブジェクトの要素を表示します。
  7. (7)clearメソッドにより、ll1オブジェクトの要素を削除します。
  8. (8)ll1オブジェクトの要素を表示します。

実行結果3

D:\JAVA>javac ExCollection4.java

D:\JAVA>java ExCollection4
add処理[R, O, A, D]
addAll処理[R, O, A, D, R, O, A, D]
set処理[J, A, V, A, R, O, A, D]
clear処理[ ]

D:\JAVA>

2List