java.util.Comparatorはコレクションをソートする際、どのようにソートするかを定義するインタフェースである。 下記のメソッドを実装することにより、ソートの方法を自分で決めることができる。実装したクラスはCollections.sort(List<T> list, Comparator<? super T> c)の第二引数に渡す。
int compare(T o1, T o2)
※総称型の導入前は、引数の型はObjectであった
javadocから引用するとパラメータと戻り値は以下となる。
パラメータ:
o1 - 比較対象の最初のオブジェクト。
o2 - 比較対象の2番目のオブジェクト。
戻り値:
最初の引数が2番目の引数より小さい場合は負の整数、両方が等しい場合は0、最初の引数が2番目の引数より大きい場合は正の整数。
なおJava8から導入されたラムダ式を使えばもっと簡潔に記載できるが、ここでは説明しない。
実際にサンプルコードをみてみよう。
import java.util.*;
public class Test{
public static void main(String[] args){
// ソートするList
List<String> list = new ArrayList<String>();
list.add("03");
list.add("1");
list.add("002");
// Comparatorを実装した匿名クラス
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
}
};
// ソート実行
Collections.sort(list, comparator);
// Listの中身を出力
System.out.println(list);
}
}
Listには文字列"03"、"1"、"002"が格納されている。これを数値の昇順にソートする。
昇順にソートするための比較ロジックはComparatorのcompareメソッド内に記述している。 このComparatorは匿名クラスである。この比較メソッドのためだけに個別クラスを作成するのが面倒なので匿名クラスにすることが多い。
Collections.sortにソートしたいListと実装したComparatorを渡している。これでListの中身がソートされる。
出力結果は以下である。
[1, 002, 03]
なおCollections.sortにはListだけ引数に持つメソッドも存在する。Comparatorを渡さず、Listだけ渡すとどうなるのか?
import java.util.*;
public class Test{
public static void main(String[] args){
// ソートするList
List<String> list = new ArrayList<String>();
list.add("03");
list.add("1");
list.add("002");
// ソート実行
Collections.sort(list);
// Listの中身を出力
System.out.println(list);
}
}
出力結果は以下である。
[002, 03, 1]
この場合、Listに格納されているStringのcompareToメソッドに従ってソートされる(Unicode値に基づいて辞書式にソート)。 StringクラスがComparableインタフェース(Comparatorとは異なるので注意)を実装しており、compareToメソッドを持っており、それが使われているのである。 Collections.sortのjavadocでは、これを「自然順序付けに従って昇順にソート」と表現している。
なおList内の要素がComparableを実装していない場合は、コンパイルエラーとなる。