このエントリーをはてなブックマークに追加

ポイントというか心にとまったことのアウトプットです。

※個人的な重要度のバイアスがかかっているので、「べつにいいかー」と思ってたりすることはメモしてません。

※手を動かして理解したことなど、間違いを含む可能性があります。

※手元の環境は断りがなければ基本は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?
      • 「具象クラスへの依存をなくすため」ということ
ArrayList<String> notGoodList = new ArrayList<>(); //非推奨?
List<String> goodList = new ArrayList<>();
  • なんでListにはなく、MapにしかgetOrDefault()がないのか
  • TreeMapに任意のキー順でソートさせるにはどうすればいいか