TreeMapのメモ

Mapでforの回し方

LinkedHashMap<Integer, Integer> map = ...
for (int key : map.keySet()) {
  System.out.println("Value: " + map.get(key));
}
for (int value : map.values()) {
  System.out.println("Value: " + value);
}
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
  System.out.println("Key: "   + entry.getKey()  );
  System.out.println("Value: " + entry.getValue());
}

TreeMapで順位で並べ替える

TreeMapはputするだけでkeyの順に並べてくれるが、Mapなのでkeyはユニークでなければならない

順位は同順である可能性もある。

成績順の印刷のためにnjun(n)に名簿番号nの生徒の順位が入っている。これをソートしなければならない。(まあ、1を捜して印刷し2を捜して印刷し...でもできないことはないが)

TreeMapを使えば追加と同時にソートされるが、同じ値はひとつになってしまうはず。そこで、

TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>();

for(int n=1;nmax>=n;n++){
    map.put(njun[n]*100+n, n);
}

順位を100倍して名簿番号を加えたものをキーにする。

インスタンスは次のようにすれば良いとの記述もあるが、積極的な理由がないので採用しない。

Map<Integer, Integer> map = new TreeMap<Integer, Integer>();

値の取り出し方。メソッドで得られるものはSetとCollectionの違いがあるが、拡張forに使え、どれもkeyの順番に取り出せる。

public Set<K> keySet()
public Collection<V> values() //(コレクションのイテレータは、値を対応するキーの昇順で返します。)
public Set<Map.Entry<K,V>> entrySet()

TreeMapで逆順

TreeMapはputするだけでkeyの順に並べてくれるが、逆順も可能だ。

TreeMap<Double, Integer> map = new TreeMap<>(Collections.reverseOrder());

コンストラクタの型変数を省略

Java7以降では、コンストラクタの型変数を省略できるというので<>と言うのが使える。つまり、

TreeMap<String,double[]> avgmap= new TreeMap<>();

と書ける

型の限定(ジェネリクス)

listやmapでは格納するものをクラスで限定する。これは1.5で導入された。intやdoubleでなく、IntegerやDoubleを指定しなければならない

色々調べるにはジェネリクス(総称型)で検索するとヒットする。型の限定は一部の機能なのだが、これが一番身近。限定しようとするのに総称というのはしっくり来ないが、Javaの歴史的な事情によるものだろう。

とにかく、intやdoubleでは次のようにコンパイルが通らない

test/MapTest.java:19: エラー: 予期しない型
        TreeMap<String,double> pdmap= new TreeMap<String,double>();
                       ^
  期待値: 参照
  検出値:    double

次のようにすればよい

TreeMap<String,Double> map = new TreeMap<String,Double>();

エラーの説明にある参照というのがポイントだろう。

ところが、Valueとしてdoubleの配列を使いたい時に、うっかりDouble[]としてエラーを出した。

TreeMap<String,Double[]> avgmap= new TreeMap<String,Double[]>();

コンパイルでエラーとなる。

$ javac gakuj/GakuJun.java 
gakuj/GakuJun.java:327: エラー: putに適切なメソッドが見つかりません(String,double[])
                avgmap.put(hr,avg);
                      ^
    メソッド TreeMap.put(String,Double[])は使用できません
      (実引数double[]はメソッド呼出変換によってDouble[]に変換できません)
    メソッド AbstractMap.put(String,Double[])は使用できません
      (実引数double[]はメソッド呼出変換によってDouble[]に変換できません)
エラー1個

Double[]が使えないということではなく、putしようとした配列が、Double[]でなくdouble[]であったということ。

指定をdouble[]にすれば受け付ける。

TreeMap<String,double[]> avgmap= new TreeMap<String,double[]>();

もちろんputする配列をDouble[]の配列にしてもよい。参照になっていればいいのだ。

Doubleのインスタンスなどしばらく作っていなかったので、Double[]をつくってみたものの入れるDoubleを作る方法をほとんど忘れていた。いろいろ試してみる。

TreeMap<String,Double[]> avgmap= new TreeMap<String,Double[]>();
Double[] avg = new Double[4];
avg[0] = new Double(1.1d);
avg[1] = Double.valueOf(2.2d);
double db = 3.3d;
avg[2] = db;
avg[3] = new Double("4.4");
for(int i=0;avg.length>i;i++)System.out.println(avg[i]);
String hr = "a";
avgmap.put(hr,avg);