Java コレクションフレームワーク

Javaコレクションフレームワークは、多数のデータをまとめて管理および処理するために用意されたもので、様々なタイプのインタフェースとクラスで構成されています。

これらのインタフェースはjava.util.Collectionとjava.util.Mapの2つのグループに分けることができます。

  • Collection
    • List
    • Set
    • Queue
    • Deque
  • Map

MapはCollectionを継承していないため狭義の意味ではコレクションではありませんが、Mapが持つ3つのコレクションビューにより、コレクション(データの集合)として扱うことができます。

コレクションフレームワークは、データ構造とアルゴリズムが提供されているため、開発コストの削減や、パフォーマンスの向上、設計コストの削減などのメリットがあります。

Java Collectionインタフェース

Collectionインタフェースは、複数の要素を保持するためのインタフェースです。Collectionは、List, Set, Queueなどのサブインタフェースを持ち、それらはそれぞれ異なる特徴を持っています。

  • List: 順序付きリストのインタフェース
  • Set: 重複を許さない集合のインタフェース
  • Queue: FIFOで要素の順序付けを行うインタフェース
  • Deque: LIFOで要素の挿入及び削除を行うインタフェース

Collectionインタフェースは、以下のようなメソッドを持っています。

  • add(E e): 要素を追加する
  • remove(Object o): 指定された要素を削除する
  • contains(Object o): 指定された要素がコレクションに含まれているかどうかを返す
  • isEmpty(): コレクションが空かどうかを返す
  • size(): コレクションの要素数を返す
  • iterator(): コレクションを反復処理するためのイテレータを返す

これらのメソッドは実装がなく、サブクラスで実装されています。

また、Collectionインタフェースは、java.utilパッケージのjava.util.Iterableインタフェースを継承しています。Iterableインタフェースは、Javaで拡張for(for-each)文を使用できるようにするためのインタフェースです。Collectionインタフェースのサブクラスはすべて、for-each文でループすることができます。

インターフェースについては、プログラミングパラダイム/OOP/インターフェースで詳しく学習できます。

Java Listインタフェース

Listインタフェースは順序付きリストのコレクションで、インデックスによってリスト内の要素にアクセスすることができます。以下のクラスで実装されています。

VectorとStackについては古くからあるレガシーなクラスのため推奨されていません。Vectorはスレッドセーフが必要な場合はCollections.synchronizedListを使用し、それ以外はArrrayListを使うほうがパフォーマンスが良くなります。StackについてはDequeを使用するよう推奨されています。

ListとArrayListは以下のように使います。

// パッケージをimportします
import java.util.List;
import java.util.ArrayList;

class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        // AbstractCollectsionで実装されているtoString()メソッドが呼ばれるので[]の中に要素が表示される
        System.out.println(list);
        // インデックスを保持するためget(インデックス番号)で要素を取得
        System.out.println(list.get(1));

        // iterableインタフェースを継承しているので拡張for文が使えます
        for(Integer i: list) {
            System.out.println(i);
        }
    }
}

Java Setインタフェース

Setインタフェースは、Javaプログラミング言語におけるデータ構造の1つで、複数の要素を保持するコレクションを表します。Setは、要素の順序を保持せず、重複を許さないという特徴があります。Collectionを継承しているため、Collectionインタフェースに定義されているすべてのメソッドを使用することができます。

Setインタフェースを実装するクラスとしては、HashSetやTreeSetがあります。HashSetは、ハッシュテーブルを使用して要素を保存し、TreeSetは、集合内の要素を自然順序で保持します。内部の実装は、実際はMapインタフェースの実装クラスであるHashMapやTreeMapの実装へ処理を委譲しています。

Java Queueインタフェース

Queueインタフェースは、Javaプログラミング言語におけるデータ構造の1つで、先入れ先出し(FIFO)のデータ構造を実装するためのインタフェースです。Collectionインタフェースを継承しているため、Collectionインタフェースに定義されているすべてのメソッドを使用することができます。

Queueインタフェースは、以下のようなメソッドを持っています。

  • offer(E e): 要素をエンキューする
  • poll(): 先頭の要素をデキューして取り出す
  • peek(): 先頭の要素を参照する

Queueインタフェースを実装するクラスとしては、LinkedListやArrayDequeがあります。

import java.util.ArrayDeque;
import java.util.Queue;

class Main {
    public static void main(String[] args) {
        // ArrayDequeを使用したQueueの生成
        Queue<String> queue = new ArrayDeque<>();

        // 要素のエンキュー
        queue.offer("Alice");
        queue.offer("Bob");
        queue.offer("Charlie");
        queue.offer("Dave");

        // キューのサイズを取得
        int size = queue.size();
        System.out.println("Queue size: " + size); // "Queue size: 4"

        // 先頭の要素を参照
        String head = queue.peek();
        System.out.println("Head of queue: " + head); // "Head of queue: Alice"

        // 要素のデキュー
        while (queue.peek() != null) {
            String s = queue.poll();
            System.out.println("Dequeued: " + s);
        }
        // "Dequeued: Alice"
        // "Dequeued: Bob"
        // "Dequeued: Charlie"
        // "Dequeued: Dave"
    }
}

Java Dequeインタフェース

Deque(Double-ended queue)は、Javaプログラミング言語におけるデータ構造の1つで、双方向キューを表すインタフェースです。Dequeは、両端から要素を追加したり削除したりできるデータ構造です。Dequeは、単方向のQueueインタフェースと比べて、より柔軟な操作ができるインタフェースです。

Dequeインタフェースは、java.utilパッケージのjava.util.Queueインタフェースを継承しています。そのため、Queueインタフェースに定義されているすべてのメソッドを使用することができます。

Dequeインタフェースは、以下のようなメソッドを持っています。

  • addFirst(E e):先頭に要素を追加する
  • addLast(E e):末尾に要素を追加する
  • offerFirst(E e):先頭に要素を追加する
  • offerLast(E e):末尾に要素を追加する
  • removeFirst():先頭の要素を削除する
  • removeLast():末尾の要素を削除する
  • pollFirst():先頭の要素を削除して取り出す
  • pollLast():末尾の要素を削除して取り出す

Dequeインタフェースを実装するクラスとしては、ArrayDequeやLinkedListがあります。

import java.util.ArrayDeque;
import java.util.Deque;

class Main {
    public static void main(String[] args) {
        // ArrayDequeを使用したDequeの生成
        Deque<String> deque = new ArrayDeque<>();

        // 要素の追加
        deque.addFirst("Alice");
        deque.addLast("Bob");
        deque.addLast("Charlie");
        deque.addLast("Dave");

        // Dequeのサイズを取得
        int size = deque.size();
        System.out.println("Deque size: " + size); // "Deque size: 4"

        // 先頭の要素を参照
        String head = deque.peekFirst();
        System.out.println("Head of deque: " + head); // "Head of deque: Alice"

        // 末尾の要素を参照
        String tail = deque.peekLast();
        System.out.println("Tail of deque: " + tail); // "Tail of deque: Dave"

        // 要素の削除
        while (deque.peekFirst() != null) {
            String s = deque.pollFirst();
            System.out.println("Dequeued from head: " + s);
        }
        // "Dequeued from head: Alice"
        // "Dequeued from head: Bob"
        // "Dequeued from head: Charlie"
        // "Dequeued from head: Dave"
    }
}

Java Mapインターフェース

Mapインタフェースは、Javaプログラミング言語におけるデータ構造の1つで、キーと値の組を保持するためのインタフェースです。Mapは、任意のオブジェクトをキーとして、任意の値を保持することができます。同じキーを使用して複数の値を保持することはできません。

Mapインタフェースは、以下のようなメソッドを持っています。

  • put(K key, V value): キーと値の組をマップに追加する
  • get(Object key): 指定されたキーに対応する値を取得する
  • remove(Object key): 指定されたキーに対応する値を削除する
  • containsKey(Object key): 指定されたキーがマップに含まれているかどうかを返す
  • isEmpty(): マップが空かどうかを返す
  • size(): マップに含まれるキーと値の組の数を返す

MapはCollectionインタフェースを実装していないので、Collectionで定義されたメソッドを使うことはできません。Mapインタフェースは、キーと値の組を保持するデータ構造ですが、そのキーや値を単独で参照することもできるように、コレクションビューを提供しています。

  • keySet(): マップのキーを保持するSetを返す
  • values(): マップの値を保持するCollectionを返す
  • entrySet(): マップのキーと値の組を保持するSetを返す

Mapインタフェースを実装するクラスとしては、HashMapやTreeMapがあります。

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

class Main {
    public static void main(String[] args) {
        // HashMapの生成
        Map<String, Integer> map = new HashMap<>();

        // 要素の追加
        map.put("Alice", 100);
        map.put("Bob", 90);
        map.put("Charlie", 80);
        map.put("Dave", 70);

        // キーを保持するSetを取得
        Set<String> keySet = map.keySet();

        // Setを繰り返し処理
        for (String key : keySet) {
            int value = map.get(key);
            System.out.println(key + ": " + value);
        }
        // "Alice: 100"
        // "Bob: 90"
        // "Charlie: 80"
        // "Dave: 70"
    }
}

この記事を書いた人

著者の画像

Jeffry Alvarado

Ex-Facebook Engineer 大学ではコンピュータサイエンスを専攻し、在学中に複数のインターンシップを経験。コンピュータサイエンスが学習できるプラットフォームRecursionを創業し、CTOとしてカリキュラム作成、ソフトウェア開発を担当。


ツイート