ポイントというか心にとまったことのアウトプットです。
※個人的な重要度のバイアスがかかっているので、「べつにいいかー」と思ってたりすることはメモしてません。
※手を動かして理解したことなど、間違いを含む可能性があります。
※手元の環境は断りがなければ基本はjava 7 をIntelliJ IDEA Ultimate on OSX で動かしてます。
「コレクションと配列」
- 配列とコレクションを使い分ける
- java7 ~ new 時の要素の型宣言は省略可(ダイアモンドオペレータ)
- コレクション内にはオブジェクトが格納されているわけではなく、変数のようにオブジェクトへの参照を持つ要素が格納されている
List<StringBuilder> l = new ArrayList<>();
l.add(new StringBuilder("aaa"));
l.add(new StringBuilder("bbb"));
l.add(new StringBuilder("ccc"));
System.out.println(l.get(1)); //bbb
l.get(1).append("test");
System.out.println(l.get(1)); //bbbtest
- コレクション要素の型は基本型(プリミティブ)は設定不可 →つまり参照型のだけ
- ArrayList のメリット・デメリット、LinkedListのメリット・デメリットを理解する
- ↑は内部のデータ構造を理解した上で理解する
long t = System.nanoTime();
List<String> al = new ArrayList<>();
for (int i = 0; i < 1000000; i ++) {
al.add(String.valueOf(i));
}
System.out.println((System.nanoTime()-t) / 1000 + "ms"); //162,542ms
t = System.nanoTime();
List<String> ll = new LinkedList<>();
for (int i = 0; i < 1000000; i ++) {
ll.add(String.valueOf(i));
}
System.out.println((System.nanoTime()-t) / 1000 + "ms"); //1,674,334ms
t = System.nanoTime();
for (int i = 0; i < 100000; i ++) {
al.remove(i);
}
System.out.println((System.nanoTime()-t) / 1000 + "ms"); //26,597,160ms
t = System.nanoTime();
for (int i = 0; i < 100000; i ++) {
ll.remove(i);
}
System.out.println((System.nanoTime()-t) / 1000 + "ms"); //154,182,850ms
- LinkedListの惨敗のような結果に終わっているが、おそらく要素数がある一定を超えると、 LinkedListが劇的に遅くなるのだと考えられる(なんでかというと、前後関係を保持しているリストであり、インデックス検索が苦手だから)
いったんはArrayListで、要素数に応じて挿入等が多い場合はLinkedListを選択するのがよさそう。
Mapの変数宣言時の要素の型は、Listと同様、基本型は設定不可
HashMap, LinkedHashMap, TreeMap の内部データ構造を理解する
- キー順序どうでもいい → HashMap
- キー順序も意味ある
- キー順でソートしたりしない → LinkedHashMap
- キー順でソートする → TreeMap
TreeMapはNavigableMapの実装により、曖昧なキー検索が可能
「セット」は重複のないリスト。順序に意味は無い
Set<String> hset1 = new HashSet<>();
hset1.add("abc");
hset1.add("def");
hset1.add("ghi");
Set<String> hset2 = new HashSet<>();
hset2.add("abc");
hset2.add("def");
hset2.add("ghi");
Set<String> hset3 = new HashSet<>();
hset3.add("ghi");
hset3.add("abc");
hset3.add("def");
System.out.println(hset1 == hset2); // false
System.out.println(hset1.equals(hset2)); // true Setは equalsで比較する
System.out.println(hset1 == hset3); // false
System.out.println(hset1.equals(hset3)); // true 順番が違っても大丈夫
- HashSet, LinkedHashSet, TreeSet の内部データ構造と使い分けを理解する
- スタック(最後に入れた(push)ものを先に取り出す(pop))
- Stackクラスは古いので、スタックを使いたいときはデックを使う
- キュー(最初に入れた(enqueue)ものを先に取り出す(dequeue))
デック(スタックにもキューにもなる)
イテレータ
- 一時中断と再開ができる
配列は使わないことを推奨(代わりにコレクション使え)
Java 6以降は
Arrays.copyOf()
か、Arrays.copyOfRange()
が効率的らしい配列のshallow copy はオブジェクトはコピーしない
Arrays.asList()
で配列をListにする。中身は共有されているので注意。コレクションから配列にするには、
toArray()
を利用する。
疑問
- 変数の型が具象型ではなくインターフェースなのはなぜか?
- 後から置き換えられるように、ということでOK?
- 「具象クラスへの依存をなくすため」ということ
- 後から置き換えられるように、ということでOK?
ArrayList<String> notGoodList = new ArrayList<>(); //非推奨?
List<String> goodList = new ArrayList<>();
- なんでListにはなく、MapにしかgetOrDefault()がないのか
- TreeMapに任意のキー順でソートさせるにはどうすればいいか