Javaのコレクションフレームワーク(List,Set,Map,Queue)

## コレクションフレームワークとは
**コレクションフレームワーク**とは、コレクション（オブジェクトの集合、プログラムの中で複数のオブジェクトを管理するためのクラスやインタフェースを総称してコレクションと呼ぶ）を操作するために用意されたJava標準のAPIで、用途に応じて、リスト（List）、Set（セット）、Map（マップ）、Queue（キュー）といったインターフェイスを使い分けることができる。

コレクションに求められる機能には、例えば次のようなものがある。
・**膨大な数のオブジェクトから目的のオブジェクトを素早く取り出したい**
・**同じインスタンスヘの参照が重複して格納されることのないようにしたい**
・**キーワードを使って目的のオブジェクトを取り出せるようにしたい**
・**特定の値で順番に並べ替えたい**

コレクションフレームワークの実装クラスは、［実装スタイル］［インターフェイス名］の形式で命名されている。

| コレクションフレームワークの主な実装クラス |  |  |
| --- | --- | --- |
| インターフェイス | 実装クラス | 概要 |
| List | ArrayList | 可変長配列 |
|  | LinkedList | リンク構造のリスト |
| Set | HashSet | 要素の集合（順不同。重複は不可） |
|  | TreeSet | 要素の集合（キーでソート。重複は不可） |
| Map | HashMap | 基本的なマップ |
|  | TreeMap | キーにより要素をソートしたマップ |
| Queue（Dequeue） | ArrayDeque | 両端キュー |

コレクションフレームワークのクラスは、主にjava.util パッケージにまとめられているので「import java.util.*;」で取り込む事が出来る。


## Listインターフェース
Listインターフェースはコレクションインターフェースの一種で、java.util.Collectionインターフェースのサブインターフェース。
Listの場合、オブジェクトの管理にインデックス(要素番号)を用いる。List生成時にデフォルトの要素数を指定する必要はなく、要素の追加や削除は自由に行える。

**配列との違い**
Listは新しい要素が追加されるたびにメモリの領域を確保するが、配列ははじめにメモリ上の連続した領域を確保する。
頻繁に要素の入れ替えが起こったり、要素の追加や削除が行われたりする場合にはListが、最初の時点で要素数が確定している場合や、何度もランダムな要素にアクセスするような場合には配列が適している。

```:サンプル
import java.util.*;

public class TestSample {
  public static void main( String args[] ) {
    List<String> list = new ArrayList<String>();
    // リストに a,b,c を追加
    list.add("a");
    list.add("b");
    list.add("c");
    
    // Listのiteratorメソッドを使ってリスト内の要素を反復するイテレータを取得、Iterator の変数に代入
    Iterator<String> iterator = list.iterator();
    
    // while文の繰り返し条件にIteratorのhasNextメソッドを利用
    while(iterator.hasNext()) {
      String str = iterator.next(); // Iteratorのnextメソッドで次のデータを取得
      System.out.println(str); // 結果：a b c を表示
    }
  }
}
```
```:出力結果
a
b
c
```

## Set（セット）インターフェース
SetインターフェースはListインターフェースと違い、要素を追加した順番を管理しない。また、同じ値のオブジェクトはセットの中に複数追加出来ない。
指定の要素が集合の中にあるか否かを素早く確認するなどに有効。
0から始まるインデックスを持たないため、要素の取り出しには拡張for文、またはiteratorメソッドをが使用する。

**HashSetクラス**
セットに属するのクラスの1つにHashSetクラスがある。HashSetクラスはジェネリクスの機能によって、インスタンスを生成するときに格納するオブジェクトの型を指定できる。String型のオブジェクトを格納する場合には、次のようにしてインスタンスを生成する。
```
// String型のHashSetインスタンスを生成
Set<String> hash = new HashSet<String>();
```
**代表的なメソッド**
・addメソッド：追加したいデータが、セット(リスト)内になければデータ追加する。
・clearメソッド：セット内の全てのデータを削除する。
・containsメソッド：指定したデータを、セットが持っていた場合trueを返す。
・isEmptyメソッド：セットがデータを持っていない場合にtrueを返す。

```:サンプル
import java.util.*;

public class TestSample {
  public static void main( String args[] ) {

    //文字列を格納するHashSetのオブジェクトを生成
    Set<String> set = new HashSet<String>();
    
    // オブジェクトsetにaddメソッドで要素を追加
    System.out.println(set.add("Jan"));
    System.out.println(set.add("Feb"));
    System.out.println(set.add("Mar"));
    System.out.println(set.add("Apr"));

    // オブジェクトsetに格納されている要素を出力
    System.out.println(set);　

    // 　containsメソッドで引数に指定した文字列がsetに含まれているか確認
    System.out.println(set.contains("Jan"));
    System.out.println(set.contains("Jun"));
  }
}
```
```:出力結果
true
true
true
true
[Feb, Apr, Jan, Mar]
true
false
```

## Map（マップ）インターフェース
Mapインターフェースは、**キーと値(オブジェクト)** のペアでオブジェクトを管理する特徴を持つ。マップにオブジェクトを格納するときには、オブジェクトとともに、それとペアになるキーを登録する。オブジェクトを取り出すときには、このキーをマップに渡す。
文字列をキーにすると、オブジェクトに名前をつけたのと同じ効果を得られ、格納したオブジェクトは、この名前(キー)を使って取得できる。ただし、このような性質から、マップでは同じ名前のキーを重複して設定することが出来ない。
```:Mapインターフェースを実装したクラスの基本的な書き方
Map< キーの型, バリューの型 > 変数名 = new Mapインターフェースを実装したクラス < キーの型, バリューの型 >();
```
※「キーの型」と「バリューの型」はそれぞれ別の型を設定することが出来る

**HashMap**
マップに属するクラスの1つにHashMapクラスがある
HashMapクラスはジェネリクスの機能によって、インスタンスを生成するときにキーと値の型を指定出来る
```
// Integer型のキーとString型のバリューを持つHashMapのインスタンスを生成
Map<Integer, String> map = new HashMap<Integer, String>();
```
**代表的なメソッド**
・putメソッド：指定したキーと指定したバリューを紐づけてデータを格納する。重複キーを指定した場合はバリューの紐づけを更新する。
・clearメソッド：マップ内からデータを全て削除する。
・containsKeyメソッド：マップが保持しているキーに対して、指定したキー名が存在した場合にtrueを返す。　キーが存在しない場合にfalseを返す。
・containsValue：マップが保持しているバリューに対して、指定したバリュー名が存在した場合にtrueを返す。バリューが存在しない場合にfalseを返す。
・isEmptyメソッド：マップ内にデータが存在しない場合にtrueを返す。データが1つでも存在する場合はfalseを返す。
・removeメソッド：マップ内のキーに対して指定したキー名が存在する場合は削除する。

```:サンプル
import java.util.*;

public class TestSample {
  public static void main( String args[] ) {
    //キーと値の両方がString型であるMapオブジェクトを生成
    Map<String, String> map = new HashMap<String, String>();

    map.put("name", "太郎");
    map.put("kana", "山田");
    map.put("address", "東京都北区");

    //entrySetメソッドは、キーと他のペアの情報をSetインタフェースを実装したオブジェクトとして取得する
    System.out.println(map.entrySet());

    //valuesメソッドでは値の一覧を取得している
    System.out.println(map.values());

    // containsKeyメソッドで指定したキー名が存在した場合にtrueを返す
    System.out.println(map.containsKey("kana"));

    //keySetメソッドはキーの一覧を取得する
    for (String str : map.keySet()){
      map.get(str);
      System.out.println(str);
    }

    map.clear(); // マップ内のデータを全て削除
    System.out.println(map); // 結果：空のマップを表示
  }
}
```
```:出力結果
[address=東京都北区, name=太郎, kana=山田]
[東京都北区, 太郎, 山田]
true
address
name
kana
{}
```

## Queue（Dequeue）インターフェース
複数データを持つことができるコレクションの中でも、「先入れ先出し(FIFO)」や「後入れ先出し(LIFO)」の特徴を持つのが Queue と Deque(デック) 
・**Queue**：データを格納した順番に取り出せる「先入れ先出し(FIFO)」の特徴を持つ。
FIFO 例) a から順に a, b, c, d とデータを格納すると最初に格納したデータ a から順に a, b, c, d とデータが取り出される。
※FIFOは「First in first out」の略。

Queueインターフェースを継承してできたのがDequeインターフェースになる
・**Deque**：先入れ先出しに加えて、最後に格納したデータから順番に取り出せる「後入れ先出し(LIFO)」の特徴を持つ。
LIFO 例) a から順に a, b, c, d とデータを格納すると最後に格納したデータ d から順に d, c, b, a とデータが取り出される。
※LIFOは「Last in first out」の略。

**ArrayDeque**
Dequeインターフェースを実装したクラスで格納するデータ数に制限なく FIFO ／ LIFO を行える特徴を持つ。
```
Deque< 型 > 変数名 = new ArrayDeque< 型 >()
```
基本的にデータの「追加」「取り出し／削除」「検索」は先頭または末尾のデータから順となる。
またnullの保持を許容しない。

```:サンプル
import java.util.Deque;
import java.util.ArrayDeque;

 class Main{
    public static void main(String[] args) {
        // String型のArrayDequeインスタンス生成
        Deque<String> deque = new ArrayDeque<String>();
        deque.add("a");
        deque.add("b");
        deque.add("c");
        
        System.out.println(deque);
    }
}
```
```:出力結果
[a, b, c]
```

## 参考記事
https://workteria.forward-soft.co.jp/blog/detail/10079

https://workteria.forward-soft.co.jp/blog/detail/10075

https://workteria.forward-soft.co.jp/blog/detail/10078