Java実践 コレクション
コレクションについての備忘録
さまざまなデータ構造
データ構造の種類
データ構造とは、「データをどのようにまとめて扱うか」ということ。
1. データ構造の種類とjava.utilパッケージのクラス(コレクションフレームワーク)
- リスト(List):順序通りに並べて格納する。中身の重複が許される。
- セット(Set):順序があるとは限らない。中身の重複が不可。
- マップ(Map):ペアを対応付けて格納する。
コレクションクラスでは、「どんな型のインスタンスでも格納することができる」が
インスタンスではないものは格納できないので注意!
2 .java.util.ArrayListについて
- ArrayList<インスタンスの型>の<インスタンスの型>の部分をジェネリクス表現という。
- Stringの部分で指定した型のインスタンスを格納する。
- 配列は宣言時に箱の数を指定する必要があるが、ArrayListをはじめとするコレクションクラスは
宣言の際に箱の数を指定しなくて良い。足りなくなれば自動で追加してくれるから必要がない。
import java.util.ArrayList; public class Main1 { public static void main(String[] args) { //<String>の部分をジェネリクス表現という //Stringの部分で指定した型のインスタンスを格納する ArrayList<String> nameList = new ArrayList<String>(); nameList.add("fumi"); nameList.add("taka"); nameList.add("pow"); System.out.println(nameList.get(1)); } }
2-1 .要素の追加・取得・削除・調査について
要素の追加
戻り値 | メソッド | 意味 |
---|---|---|
boolean | add(インスタンスの型) | リストの最後に要素を追加 |
void | add(int, インスタンスの型) | リストのint番目に要素を追加 |
インスタンスの型 | set(int, インスタンスの型) | リストのint番目の要素を上書き |
要素の取得
戻り値 | メソッド | 意味 |
---|---|---|
インスタンスの型 | get(int) | int番目の要素を取得 |
リストの調査
戻り値 | メソッド | 意味 |
---|---|---|
int | size() | リストに格納されている要素数を返す |
boolean | isEmpty() | 要素数がゼロであるか判定 |
boolean | contain(インスタンスの型) | 指定要素が含まれているかどうか |
int | indexOf(インスタンスの型) | 指定要素がリストの何番目に格納されているか |
イテレータを返す
戻り値 | メソッド | 意味 |
---|---|---|
Iterator<インスタンスの型> | iterator() | イテレータの取得。要素を順に処理するイテレータを返却。 |
要素を削除する
戻り値 | メソッド | 意味 |
---|---|---|
void | clear() | 要素を全て削除する。 |
インスタンスの型 | remove(int) | int番目の要素を削除する。 |
2-2 .イテレータについて
- イテレータとは、リストの中身を1つずつ取り出すための専用の方法。
ざっくりした方法
Iterator< リスト要素の型 > ite = リスト変数インスタンス.iterator(); // インスタンス生成にnewしない。 // newの代わりにリスト変数インスタンスのiterator()を呼び出す。 // 矢印は、java.util.Iterator< リスト要素の型 >のインスタンスとする。
戻り値 | メソッド | 意味 |
---|---|---|
boolean | hasNext() | 次の要素を指せるか調査する。指せればtrueを返却。 |
インスタンスの型 | next() | 次の要素を指して、その内容(インスタンスの型の値)を返却。 |
3 .3種類の方法でArrayListの要素を取り出すまとめ
ArrayList<String> nameList = new ArrayList<String>(); nameList.add("fumi"); nameList.add("taka"); nameList.add("pow"); // 1. for文 for(int count = 0; count < nameList.size(); ++count) { System.out.println(nameList.get(count)); } // 2. 拡張for文 for(String output : nameList) { System.out.println(output); } // 3. イテレータ Iterator<String> ite = nameList.iterator(); //Iteratorの取得した時点では、nameListの先頭要素である0番目の要素"taka"より前をさした状態となる。 while(ite.hasNext()){ //矢印を次に進められるならtrue String outputName = ite.next(); //矢印を次に進めて、取り出す System.out.println(outputName); }
4 .java.util.LinkedListについて
4-1. ArrayListとLinkedListの内部構造がの違い
- ArrayList:それぞれの箱が整列している。
- LinkedList:それぞれの箱自体は、バラバラに存在する。しかし、それぞれの箱は「次にどの箱と繋がるか」という連結情報を持っているので数珠つなぎになっている。
4-2. 内部構造の違いによる得意・不得意
比較項目 | ArrayList | LinkedList |
---|---|---|
内部構造 | 配列(並んだ箱) | 連結リスト(数珠つなぎの箱) |
add(), remove() 要素の挿入・削除 ※1 | 遅い | 高速 |
get(int) 指定位置の要素の取得 ※2 | 高速 | 遅い |
※1
リストの途中に要素を追加したり、削除したりするのはArrayListは苦手とする。理由は追加したり削除した要素の後ろの要素をコピーして後ろに移動するもしくは前に詰めることを玉突き方式で行う必要がある。 LinkedListが得意な理由は、要素の追加または削除があっても1つの要素の連結情報を書き換えれば良いだけなので高速に処理できる。
※2
逆にLinkedListが指定位置の要素の取得が不得意な理由は、順番を表す番号の情報を持たないため先頭から順番に数えて処理を行う必要があるため。
4-3. ざっくりとらえてどちらもList
- ArrayListもLinkedListも
java.util.List
インターフェースを実装している。
List<String> names1 = new ArrayList<String>(); List<String> names2 = new LinkedList<String>();
上記のコードでは、右辺では具体的なクラスをnewしてインスタンス生成し
左辺では、あいまいなList型の変数を利用している。newするクラスはどの実装を使うか意識する必要があるが、そのインスタンスを利用する際は「ざっくりList」と捉えて利用する方がメリットが大きい。
例)
//メソッド1 public void outPut(ArrayList<String>) //ArrayList<String>しか引数として渡せない { 〜なんらかの処理〜 } //メソッド2 public void outPut(List<Strign>) //ArrayList<String>もLinkedList<String>も渡せちゃう { 〜なんらかの処理〜 }
=== ポイント===
下記には極力あいまいな型(インターフェース型)を利用できないか検討し利用する。
- 引数
- 戻り値
- ローカル変数
5 .java.util.HashSetについて
Setインターフェースを実装するクラスは、複数の情報を重複なく格納する集合(セット)
というデータ構造である。Setの基本特性
- 要素の重複が許されない。
- 要素には、順序関係がない。
5-1 . Setインターフェースが備えるメソッドについて
要素の追加
戻り値 | メソッド | 意味 |
---|---|---|
boolean | add(要素) | セットに要素を追加 |
セットの調査
戻り値 | メソッド | 意味 |
---|---|---|
int | size() | 格納されている要素数を返す |
boolean | isEmpty | 要素数がゼロであるかを判定 |
boolean | contains(要素) | 指定要素がセットに含まれているか判定 |
要素を削除する
戻り値 | メソッド | 意味 |
---|---|---|
void | clear() | 要素を全て削除する |
boolean | remove(要素) | 指定した要素を削除する |
イテレータを返す
戻り値 | メソッド | 意味 |
---|---|---|
Iterator<要素> | iterator() | 要素を順に処理するイテレータを返す |
5-2 . Setインターフェースのメソッド注意点について
1.重複した要素は無視される
Set<String> colors = new HashSet<String>(); colors.add("赤"); colors.add("青"); colors.add("黄"); colors.add("黄"); //無視される System.out.println(colors.size()); // => 実行結果:3
2.要素を取得するためには、拡張for文やイテレータを使う(get()がない)
- どのような順序で取り出すことができるかは一切確約されていない。
//拡張for文で取り出し for(String str: colors { System.out.println(str); } //イテレータ で取り出し Iterator<String> ite = colors.iterator(); while(ite.hasNext()) { System.out.println(ite.next()); }
5-3 . LinkedHashSetとTreeSetについて
- HashSetクラス以外にもSetインターフェースを実装しているクラスがある。
そして、HashSetと違って要素同士の順序を保証してくれる。- LinkedHashSet ⇨ 値を格納した順序に整列
- TreeSet ⇨ 自然順序で整列(Stringクラスでは辞書順となる)
//LinkedHashSetクラスでデータ追加順位取り出す Set<String> names1 = new LinkedHashSet<String>(); names1.add("fumi"); names1.add("taka"); names1.add("pow"); Iterator<String> ite = names1.iterator(); while(ite.hasNext()) { System.out.println(ite.next()); } //TreeSetクラスで辞書順にデータを取り出す Set<String> names2 = new TreeSet<String>(); names2.add("con"); names2.add("app"); names2.add("bob"); for(String name : names2) {#### <b>5-1 . Setインターフェースが備えるメソッドについて</b> <u>要素の追加</u> |戻り値|メソッド|意味| |----|----|----| |boolean|add(要素)|セットに要素を追加| System.out.println(name); }
6 .java.util.HashMapについて
- Mapとは、「キー」と「値」のペアで格納するデータ構造。
- HshMapクラスは、java.util.Mapインターフェースを実装するクラスでよく利用される。
6-1 . HashMapクラスの利用について
- インスタンス生成方法
Map< キーの型 , 値の型 > Map変数 = new HashMap< キーの型 , 値の型 >();
- HashMapクラスが備えるメソッドについて
- 注意:Mapでは値の重複は許されるが、キーの重複は許されない!
同じキーを指定して値をput()を使うと値が上書きされてしまうので注意すること!
- 注意:Mapでは値の重複は許されるが、キーの重複は許されない!
要素の格納
戻り値 | メソッド | 意味 |
---|---|---|
値 | put(キー, 値) | マップにキーと値のペアを格納 |
要素の取り出し
戻り値 | メソッド | 意味 |
---|---|---|
値 | get(キー) | キーに対応する値を取得(なければnull) |
マップを調査する
戻り値 | メソッド | 意味 |
---|---|---|
int | size() | 格納されているペアの数を調査 |
boolean | isEmpty() | 要素数がゼロであるかどうかを判定 |
boolean | containsKey(キー) | 指定したキーがマップのキーに含まれているかどうか調査 |
boolean | containsKey(値) | 指定した値がマップの値に含まれているかどうか調査 |
要素を削除する
戻り値 | メソッド | 意味 |
---|---|---|
void | clear() | 要素を全て削除する |
値 | remove(キー) | 指定したキーの値を削除する |
格納されているキーの返却
戻り値 | メソッド | 意味 |
---|---|---|
Set<キー> | keySet() | 格納されているキーの一覧を返す |
6-2 . HashMapの中身1つずつ取り出す方法
1. Mapに格納されているキー一覧を取得
2. 各キーに対応する値を取得
HashMapは順序保証しないので毎回同じ取得順序になるとは限らない。
必要であれば、LinkedHashMapで、Mapへ追加順で取り出す。
または、TreeMapで自然順序で取り出す。(メモ:Integerだと多い順っぽい)
Map<String, Integer> pop = new HashMap<String, Integer>(); pop.put("A市", 300); pop.put("b市", 500); pop.put("c市", 1000); //c市の価を上書き pop.put("c市", 1200); //1.キーの一覧を取得 Set<String> keys = pop.keySet(); //2.値の取得 for(String key : keys) { System.out.println(pop.get(key)); }