【Java】コレクションフレームワーク ( List )

# コレクションフレームワーク
この記事では、java.utilをして利用できる便利なクラスを学んで行きます。

## コレクションフレームワークとは
そもそも、フレームワークとは概念的な意味で、
- 「**何かの枠組み**」
- 「**システム開発を楽に行えるように用意された、プログラムとかのひな形**」

のことです。つまり、
`コレクションフレームワーク = 便利な機能をまとめたもの`みたいな考え方でいいと思います。

これらの **用意された便利な機能を、柔軟に扱うことを考えられているのがコレクション・フレームワーク**です。

## java.utilパッケージとは
java.utilは Javaのフレームワークの一種で、Javaで使われる 、以下のような データを表現するのに必要なデータ構造が一通り揃っています。

- [配列操作]
- イベント
- モデル
- 日付および時間...

その中でも代表的な「[配列操作]」をするために3つの便利なクラスがあります。それが、**「List」, 「Set」, 「Map」**です。

1. *リスト(List) 値が順番に並んで格納したもの*
2. *セット(Set) 順序があるとは限らず格納され、同じ値のものが1つだけのもの*
3. *マップ(Map)ペアで対応づけて格納し、キーごとに値が対応したもの*


# 【List】順序を持ったコレクション

## Listとは
リストは配列によく似た性質を持つ「`0から始まるインデックスごとにデータが入ったもの`」です。
インデックスによって要素を挿入したり要素にアクセスしたりする位置を自由に変更することができます。

## List と 配列 の違い
Listは、持っている特長が [配列] に非常によく似ているものの、Javaの「 *通常の[配列操作]とは少々異なります。* 」

- 【配列】
  - 最初にサイズを決めるため、<font color="Red">「*後からサイズを拡張することができない*」</font>
- 【Listクラス】
  - 要素を追加した分だけ<font color="Blue">「*自動的にサイズが拡張される動的な配列*」を作ることができる。</font>
  - Listクラスのメソッドを使うことで<font color="Blue">「*値を追加したり途中に挿入したり、削除することができる。*」</font>

## Listの定義の仕方
Listの基本的な定義の仕方はこちらになります。

```
リストインターフェース名<型> インスタンス名 = new コンストラクタ名<型>();
```

ちなみに、Java 1.4以降 ダイヤモンド演算子"<>"を用いて以下のように書くことが可能ですので、基本この型で書いていいと思います。

```java
// ArrayListに<型>を指定しない
List<String> sampleList = new ArrayList<>();
```

## ArrayList（可変長配列)

### ArrayList とは
Listインタフェースを実装したコレクションクラスです。
「Array」 という名にあるように *「配列のような感覚」で扱うことができる。*
JavaのArrayListは大きさが決まっていない配列のようなものとイメージしてください。ArrayListは、複数の値を管理する時に使います。

### ArrayListの特徴
メリットはこちら

- ArrayListクラス は配列でリストを実装しており、「添え字による要素へのアクセス」が高速です。
- 要素の「追加」が、新たな要素を末尾へ加えるだけなので楽

短所はこちら

- 配列の途中の位置への要素の「挿入」や「削除」に関しては、 挿入・削除した位置以降の全ての要素の位置を移動させるという処理を行う必要があるため低速になる。

### ArrayList の宣言・初期化
書き方はこちらです。

```java
// 基本の定義の仕方
ArrayList<型> 変数名 = new ArrayList<型>();

// サンプルコード
List<String> sampleList = new ArrayList<String>();
## ArrayListクラスの使用例

2パターンありますので、見ていただきます。
やってることは同じですから実行結果は変わりませんのでお好みで。

```java
package practiceListClass;

//utilパッケージのArrayListクラスをimport
import java.util.ArrayList;
//utilパッケージのListクラスをimport
import java.util.List;

public class ArrayAboutMain {

    public static void main(String args[]) {

        // ここから =====================================
        List<String> sampleList = new ArrayList<String>();
        sampleList.add("1回目のリストに格納");
        sampleList.add("2回目のリストに格納");
        // ここまで =====================================

        // リストに格納した全要素を順番に出力
        for (int i = 0; i < sampleList.size(); i++) {
            System.out.println(sampleList.get(i));
        }
    }

}
```

2パターン目。addの書き方が少し違うバージョン。


```java
        // ここから =====================================
        List<String> sampleList = new ArrayList<String>();
        sampleList = new ArrayList<String>() {
            {
                add("1回目のリストに格納");
                add("2回目のリストに格納");
            }
        };
        // ここまで =====================================
```
実行結果はこちら

```
1回目のリストに格納
2回目のリストに格納
```

上記のコードを解説すると
生成したArrayListクラスのインスタンスを、Listインタフェース型の変数sampleListに保持しています。

Listインタフェースでは、

- 要素の追加: addメソッド
- 値を取り出すとき: getメソッド

を使用してください。




## LinkedList（連結リスト）

### LinkedListとは
LinkedListは、要素同士を前後双方向のリンクで参照するリンクリストを表します。

### LinkedListの特徴

- 要素の挿入／削除はリンクの付け替えで済むため、ArrayListに較べても高速
- インデックス値によるランダムなアクセスは苦手



LinkedListクラス はリスト構造を使用して実装しています。
このため、「添え字による要素へのアクセス」は、毎回先頭から順番に要素をたどっていきながら
目的の位置を探す（添え字の番号まで移動していく）必要があるため、低速です。



### LinkedList の宣言・初期化

```java
// 基本の定義の仕方
LinkedList<型> 変数名 = new LinkedList<型>();
// サンプルコード
List<String> sampleList = new LinkedList<String>();
```

## LinkedList の使用例
ArrayListとやってることは変わりませんが、コピペ用でこちらも載せておきます。

こちらも2パターンありますので、見ていただきます。
やってることは同じですから実行結果は変わりませんのでお好みで。

```java
package practiceListClass;

//utilパッケージのArrayListクラスをimport
import java.util.ArrayList;
//utilパッケージのListクラスをimport
import java.util.List;

public class ArrayAboutMain {

    public static void main(String args[]) {

        // ここから =====================================
         List<String> sampleList = new LinkedList<String>();
        sampleList.add("1回目のリストに格納");
        sampleList.add("2回目のリストに格納");
        // ここまで =====================================

        // リストに格納した全要素を順番に出力
        for (int i = 0; i < sampleList.size(); i++) {
            System.out.println(sampleList.get(i));
        }
    }

}
```

2パターン目。addの書き方が少し違うバージョン。


```java
        // ここから =====================================
        List<String> sampleList = new LinkedList<String>();
        sampleList = new LinkedList<String>() {
            {
                add("1回目のリストに格納");
                add("2回目のリストに格納");
            }
        };
        // ここまで =====================================
```
実行結果はこちら

```
1回目のリストに格納
2回目のリストに格納
```

上記のコードを解説すると
生成したArrayListクラスのインスタンスを、Listインタフェース型の変数sampleListに保持しています。

Listインタフェースでは、

- 要素の追加: addメソッド
- 値を取り出すとき: getメソッド

を使用してください。


## List系クラス チートシート

各クラスの特徴を踏まえて、用途に応じてクラスを選択することが Listインタフェースを使いこなす
ポイントとなります。
以下のように、

- 挿入／削除操作が多い状況ではLinkedList
- それ以外の場合はArrayList

という使い分けになると思います。


| クラス     | 概要                                                                   | 長所                                                                                               | 短所                                                                                       | 使う場面                                                                                                                  | 
| ---------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | 
| ArrayList  | 複数の値を管理する時に使う、「大きさの決まっていない配列のようなもの」 | 添え字による要素へのアクセス」が高速<br><br>要素の「追加」が、新たな要素を末尾へ加えるだけなので楽 | 要素を追加するスピードが遅い                                                               | 配列内の要素に対してランダムなアクセスを必要とし、配列内の要素に対して挿入／削除の操作があまり必要ない場合                | 
| LinkedList | 要素同士を前後双方向のリンクで参照するリンクリストを表します。         | 要素の挿入／削除はリンクの付け替えで済むため高速                                                   | ・特定の要素にアクセスするスピードが遅い<br>・インデックス値によるランダムなアクセスは苦手 | 要素数が多くて、且つ要素の挿入・削除を頻繁に行うことが予想 でき、配列内の要素に対してランダムなアクセスを必要としない場面 |