Java独習(第６章)

この記事ではJava独習の第６章（コレクションフレームワーク）についてのまとめを行います。
コンテンツは以下の通り
<b>・コレクションフレームワークの基本
・リスト
・セット
・マップ
・スタック/キュー</b>

6-1 コレクションフレームワークの仕組み
コレクション＝オブジェクトの集合を表す仕組み
配列との違いは以下のようなものがあげられる
・既知のデータ構造やアルゴリズムを取り込むことができパフォーマンスが高い
・共通的な操作をインターフェイスとして定義しているのでデータ構造やアルゴリズムにとらわれず同じように操作可能
Collectionのサブインターインターフェイスとして以下のようなものがある
・リスト(順序を持ち重複OK)-ArrayListとLinked List
・セット(重複NG)-hashSetとLinkedHashsetとTreeSet
・マップ(キーと値の組み合わせで管理)-HahsMapとTreeMap
・スタック/キュー(戦闘と末尾の追加や削除が可能)-ArrayDequeとLinkedList

コレクションのインターフェイス化は
<b>
インターフェイス型 <要素型> = new 実装クラス型<>(引数....)
List <String> = new ArrayList<>();
</b>

ArrayList<String> data = new ArrayList<>();
でもいいが、実数型を引数として渡すのは望ましくない
もしLinkedList(別の実装)に変える場合全部変えなければいけないため

<b>ジェネリクス=汎用的なクラスやメゾットを特定の型に紐づけるための仕組み</b>
List<String>のように本来の汎用型のように<...>の形式で個別の型を割り当てることによってなんでもOkとするわけではなく、文字列だけになる的な

要素を順番に取り出すときはforを使用
内部的にはイテレータを利用している。イテレーターとはコレクションの要素を順番に取り出す仕組み
イテレーターのインターフェイスは以下のようなものがある
boolean has Next() 次の要素が存在するか
E next() 次の要素の取得(Eは要素の型)
void remove 現在の要素の削除

```
Java
import java.util.ArrayList;

public class IteratorRemove {

  public static void main(String[] args) {
    var data = new ArrayList<String>() {
      {
        add("バラ");
        add("ひまわり");
        add("あさがお");
      }
    };

    var ite = data.iterator();
    while (ite.hasNext()) {
      System.out.println(ite.next());
      ite.remove();
    }
    System.out.println(data);
  }
}

```
ite.removeをコメントアウトするとこの場合バラ・ひまわり・あさがおと順番に出てきて最後に配列が表れるが、removeメゾットを使用することで配列が表れない

逆順から読み込むときはiteratorメゾットではなく、listIteratorメゾットでListIteratorメゾットを取得

```
Java
import java.util.ArrayList;

public class IteratorList {

  public static void main(String[] args) {
    var data = new ArrayList<String>() {
      {
        add("バラ");
        add("ひまわり");
        add("あさがお");
      }
    };

    var ite = data.listIterator(data.size());
    while (ite.hasPrevious()) {
      System.out.println(ite.previous());
    }
  }
}
```

配列とコレクションの変換は以下のようにする

```
Java
import java.util.ArrayList;
import java.util.Arrays;

public class CollToArray {

  public static void main(String[] args) {
    var data = new ArrayList<String>(Arrays.asList("バラ", "ひまわり", "あさがお"));
    var strs = new String[data.size()];
    data.toArray(strs);
    data.set(0, "チューリップ");
    System.out.println(Arrays.toString(strs));
    System.out.println(data);
  }
}
```
しかし、あくまでこれは配列であるのでリストの追加や削除は配列をコピーして新規にリストを作成
Colelction.addAllメゾットを利用

```
Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class CollAddAll {

  public static void main(String[] args) {
    var data = new String[] { "バラ", "ひまわり", "あさがお"};
    var list = new ArrayList<String>();
    Collections.addAll(list, data);
    list.set(0, "チューリップ");
    list.add("さくら");
    list.remove(1);

    System.out.println(list);
    System.out.println(Arrays.toString(data));
  }
}
```

コレクションから配列はtoArrayメゾットつかう

```
Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class CollAddAll {

  public static void main(String[] args) {
    var data = new String[] { "バラ", "ひまわり", "あさがお"};
    var list = new ArrayList<String>();
    Collections.addAll(list, data);
    list.set(0, "チューリップ");
    list.add("さくら");
    list.remove(1);

    System.out.println(list);
    System.out.println(Arrays.toString(data));
  }
}
```

変更不能にするためにはunmodifiablexxxx用いる
unmodifiableListやunmodifiableMapなど


<b>6-2　リスト</b>
リストの実装には以下のようなものがある
ArrayList, LinkedList, Vector(なお今は使わない)

ArrayListの基本メゾット

```
Java
public class ListArray {

  public static void main(String[] args) {
    var list = new ArrayList<Integer>(Arrays.asList(10, 15, 30, 60));
    var list2 = new ArrayList<Integer>(Arrays.asList(1, 5, 3, 6));
    var list3 = new ArrayList<Integer>(Arrays.asList(1, 2, 3));

    for (var i : list) {
      System.out.println(i / 5);
    }

    System.out.println(list.size()); //4
    System.out.println(list.get(0)); //10
    System.out.println(list.contains(30)); //true
    System.out.println(list.indexOf(30)); //2
    System.out.println(list.lastIndexOf(30)); 
    System.out.println(list.isEmpty());
    System.out.println(list.remove(0));
    System.out.println(list);

    list.addAll(list2);
    System.out.println(list);

    list.removeAll(list3);
    System.out.println(list);

    list.set(0, 100);
    var data = list.toArray();
    System.out.println(Arrays.toString(data));
  }
}
```

LinkedListは個別の要素のアクセスは戦闘と末尾のリンクからたどる
＝インデックス値による要素の読み書きには不向きで挿入や削除は早い

```
Java
public class ListLinked {

  public static void main(String[] args) {
    var list = new LinkedList<String>(Arrays.asList("うさぎ", "たつ", "へび"));
    System.out.println(list);

    list.addFirst("とら");
    list.addLast("うま");
    System.out.println(list);
    System.out.println(list.getFirst());
    System.out.println(list.getLast());
    System.out.println(list.removeFirst());
    System.out.println(list.removeLast());
    System.out.println(list);
  }
}

```

6-3 セット
重複した要素は無視で順番を持たない集合
HashSetとLinkedHashSetとTreeSetがある

２つのセットがあるとしたら
retainAllは共通部分
removeAllは片方にあるもののみ
addAllはすべての要素

```
Java
public class SetBasic {

  public static void main(String[] args) {
    var hs = new HashSet<Integer>(Arrays.asList(1, 20, 30, 10, 30, 60, 15));
    var hs2 = new HashSet<Integer>(Arrays.asList(10 ,20 ,99));

    System.out.println(hs);
    System.out.println(hs.size());
    System.out.println(hs.isEmpty());
    System.out.println(hs.contains(1));
    System.out.println(hs.containsAll(hs2));
    System.out.println(hs.remove(1));
    System.out.println(hs);

    hs.addAll(hs2);
    System.out.println(hs);

    hs.retainAll(hs2);
    System.out.println(hs);

    var hs3 = new HashSet<Integer>(Arrays.asList(1, 10 , 20));
    hs.removeAll(hs3);
    System.out.println(hs);
  }
}

```


HashSetは一切並び順を管理しないが、TreeSetは並び順を管理

```
Java
public class SetTree {

  public static void main(String[] args) {
    var ts = new TreeSet<Integer>(Arrays.asList(1, 20, 30, 10, 60, 15));
    System.out.println(ts);
    System.out.println(ts.descendingSet());
    System.out.println(ts.ceiling(15));
    System.out.println(ts.lower(15));
    System.out.println(ts.tailSet(15));
    System.out.println(ts.headSet(30, true));
  }
}

```


6-4 Map
一意のキーと値で管理
HashMapを最も利用するので本記事ではいったんTreeHashはおいておく
HashMapはキーの順序が保証されないので順番に意味があるものはTreemapをつかう

HashMapは内部的にハッシュ票を持っていて要素を保存するときにキーから八種値を求めてどこに保存するか決める
HashMapの基本動作

```
Java
public class MapHash {

  public static void main(String[] args) {
    var map = new HashMap<String, String>(Map.of("Rose", "バラ",
      "Sunflower", "ひまわり", "Morning Glory", "あさがお"));
    System.out.println(map.containsKey("Rose"));
    System.out.println(map.containsValue("バラ"));
    System.out.println(map.isEmpty());

    for (var key : map.keySet()) {
      System.out.println(key);
    }

    for (var value : map.values()) {
      System.out.println(value);
    }
    map.replace("Rose", "薔薇");
    map.replace("Sunflower", "ひまわり", "向日葵");

    for (var entry : map.entrySet()) {
      System.out.println(entry.getKey() + ":" + entry.getValue());
    }
  }
}

```
mapはコレクションのサブインターフェイスではないためfor命令に渡すことはできない

6-5　スタック
ArrayDequeは循環配列

```
Java
public class DequeArray {

  public static void main(String[] args) {
    var data = new ArrayDeque<Integer>();
    data.addLast(10);
    data.addLast(15);
    data.addLast(30);

    System.out.println(data);
    System.out.println(data.removeLast());
    System.out.println(data);

    var data2 = new ArrayDeque<Integer>();
    data2.addLast(10);
    data2.addLast(15);
    data2.addLast(30);

    System.out.println(data2);
    System.out.println(data2.removeFirst());
    System.out.println(data2);
  }
}

```