1. Collection インターフェースとは
Java におけるインターフェースは契約のようなものです。クラスがインターフェースを実装するなら、そのメソッドすべての実装を提供しなければなりません。インターフェース自体は状態を保持せず、コードを含みません(例外もあります。Java 8 以降は default メソッドが可能ですが、ここでは基本の考え方が重要です)。
Collection は Java の大半のコレクションの基本インターフェースです。コレクションが何をできるかを定義します: 要素の追加、削除、サイズの取得、要素の有無の確認など。
public interface Collection<E> extends Iterable<E> {
int size();
boolean isEmpty();
boolean contains(Object o);
boolean add(E e);
boolean remove(Object o);
void clear();
Iterator<E> iterator();
// ... ほかにも便利なメソッドがたくさんある
}
主なメソッド:
- add(E e) — 要素を追加する。
- remove(Object o) — 要素を削除する。
- size() — 要素数を取得する。
- isEmpty() — 空かどうかを確認する。
- contains(Object o) — 要素の存在を確認する。
- clear() — コレクションを空にする。
- iterator() — 反復処理用のイテレーターを取得する。
なぜ Map は Collection を継承しないのか?
Map はコレクションの中でも特別です。Map は単なる要素集合ではなく「キー → 値」のペア集合だからです。契約もメソッド群も異なります。例えば、Map には add メソッドはありません。追加は put(key, value) で行い、キーを知らずに値の有無を調べても意味がありません。
2. コレクションの階層
主要インターフェースの「木構造」は次のとおりです:
Iterable
|
Collection
/ | \
List Set Queue
|
Deque
- Iterable — 最も基本的なインターフェース。for-each で反復できるもの。
- Collection — Iterable を拡張し、要素コレクションの操作を追加。
- 主な枝は 3 つ:
- List — 順序付きのリスト。重複可。
- Set — 一意な要素の集合。順序は実装に依存。
- Queue — キュー(通常は FIFO)。亜種として Deque(両端キュー)。
一方、Map は別系統です:
Map
/ \
HashMap TreeMap
階層の可視化(図)
+--------------------+
| Iterable<E> |
+--------------------+
|
+--------------------+
| Collection<E> |
+--------------------+
/ | \
+--------+ +-------+ +-------+
| List | | Set | | Queue |
+--------+ +-------+ +-------+
|
+------+
|Deque |
+------+
+--------------------+
| Map<K,V> |
+--------------------+
3. List: 順序付きで重複を許すコレクション
List は次のようなコレクションです:
- 要素の順序が重要(1 番目、2 番目、3 番目…)。
- 同じ要素(重複)を許可。
- インデックスで要素を取得(list.get(2))、置換、任意の位置に挿入できる。
実装例: ArrayList — インデックスアクセスが高速。LinkedList — 中間での挿入/削除が多い場合に適する。
import java.util.*;
List<String> shoppingList = new ArrayList<>();
shoppingList.add("牛乳");
shoppingList.add("パン");
shoppingList.add("チーズ");
shoppingList.add("パン"); // 重複は許可される!
System.out.println(shoppingList.get(1)); // "パン"
List の代表的なメソッド:
- add(E e)、add(int index, E e)
- get(int index)、set(int index, E e)
- remove(int index)、remove(Object o)
- indexOf(Object o)、lastIndexOf(Object o)
4. Set: 一意な要素の集合
Set は次のようなコレクションです:
- 各要素が一意(重複なし)。
- HashSet では順序は保証されず、TreeSet ではソートされる場合があり、LinkedHashSet では挿入順を保持。
実装例: HashSet、TreeSet、LinkedHashSet。
import java.util.*;
Set<String> uniqueNames = new HashSet<>();
uniqueNames.add("Anya");
uniqueNames.add("Boris");
uniqueNames.add("Anya"); // 追加されません — すでに存在します!
System.out.println(uniqueNames.contains("Anya")); // true
System.out.println(uniqueNames.size()); // 2
Set の代表的なメソッド:
- add(E e)、remove(Object o)
- contains(Object o)
- size()、isEmpty()
5. Map: キーと値のペアのコレクション
Map は次のようなコレクションです:
- 各要素は キー → 値 のペア。
- キーは一意、値は重複可。
- キーによる高速アクセス。
実装例: HashMap、TreeMap、LinkedHashMap。
import java.util.*;
Map<String, String> phoneBook = new HashMap<>();
phoneBook.put("Anya", "+19991112233");
phoneBook.put("Boris", "+19994445566");
phoneBook.put("Anya", "+19990001122"); // Anya の番号を上書きします!
System.out.println(phoneBook.get("Anya")); // "+19990001122"
System.out.println(phoneBook.containsKey("Boris")); // true
Map の代表的なメソッド:
- put(K key, V value)、get(K key)
- remove(K key)
- containsKey(K key)、containsValue(V value)
- keySet()、values()、entrySet()
6. 階層の可視化: 1 枚にまとめると
簡単なまとめ表:
| インターフェース | 説明 | 実装例 | 主な特徴 |
|---|---|---|---|
|
順序付きリスト | |
インデックスでアクセス、重複可 |
|
一意な値の集合 | |
一意な要素のみ |
|
キーと値のペア | |
キーは一意、値は任意 |
階層の図:
Collection
/ | \
List Set Queue
|
Deque
Map (別系統)
7. どのインターフェースをいつ使うか
List
- 要素の順序が重要なとき(例: ユーザー操作の履歴)。
- 重複が必要なとき(例: 注文の明細)。
- インデックスによる高速なアクセスや置換が必要なとき。
Set
- 一意性が必要なとき(メール、ログイン、ID など)。
- 順序が重要でない、または自動的にソートされた集合が必要なとき(TreeSet)。
Map
- キーと値を対応付けたいとき(id → オブジェクト、ログイン → プロフィール)。
- キーによる高速検索が必要なとき。
- キーは一意である必要があり、値は一意でなくてよいとき。
8. コレクション階層を扱う際のよくある誤り
エラー No. 1: 変数の宣言で不適切なインターフェースを使う。 ArrayList<String> list = new ArrayList<>(); のように書くと、実装に強く結び付いてしまいます。望ましいのは List<String> list = new ArrayList<>(); — この方が実装を差し替えやすくなります。
エラー No. 2: Set に重複を追加しようとして、反映されると期待する。 これはバグではなく仕様です。Set は定義上、重複を保持しません。再挿入は無視されます。
エラー No. 3: Map を通常のコレクションとして扱う。 Map はリストでも集合でもありません。走査には keySet()、values()、entrySet() を使いましょう。
エラー No. 4: HashSet や HashMap に順序を期待する。 HashSet と HashMap は順序を保証しません。順序が重要なら LinkedHashSet や LinkedHashMap を使いましょう。
エラー No. 5: 一意要素に List を使う。 一意性が必要なら Set を使いましょう。List は重複を防ぎません。
GO TO FULL VERSION