【Java】Listのソート方法
Collections クラス
Collectionsクラスは、ListやMapに関連するstaticなメソッドが定義されています。
その中の 1 つにsort()があります。
sort()はオーバーロードされていて、Comparableを使うものとComparatorを使うものの 2 種類があります。
Comparable によるソート
以下はIntegerとStringのソート方法の例になります。
Integer[] nums = {10, 4, 6, 2, 8};
List<Integer> list = Arrays.asList(nums);
//昇順ソート 2, 4, 6, 8, 10
Collections.sort(list);
//降順ソート 10, 8, 6, 4, 2
Collections.sort(list, Collections.reverseOrder());String[] strs = {"ABC", "abc", "123", "1A", "A12"};
List<String> list = Arrays.asList(strs);
//昇順ソート 123, 1A, A12, ABC, abc
Collections.sort(list);
//降順ソート abc, ABC, A12, 1A, 123
Collections.sort(list, Collections.reverseOrder());どちらもsort()の引数にListを渡すだけでソートされていることがわかります。
では、自作したクラスではどうでしょうか。
public class MyClass {
private int num;
private String str;
//Constructor
public MyClass(int num, String str) {
this.num = num;
this.str = str;
}
}List<MyClass> list = new ArrayList<>();
list.add(new MyClass(1, "ABC"));
list.add(new MyClass(2, "ABC"));
list.add(new MyClass(1, "BAC"));
list.add(new MyClass(0, "CCC"));
list.add(new MyClass(2, "000"));
//昇順ソート
Collections.sort(list);
//降順ソート
Collections.sort(list, Collections.reverseOrder());これだけではソートは実行されません。なぜならどのようにソートをすれば良いかがわからないからです。
これを定義するのがComparableになります。
public class MyClass implements Comparable<MyClass> {
//省略
@Override
public int compareTo(MyClass another) {
int cmp = 0;
//numを比較する
if ((cmp = this.num - another.num) != 0) {
return cmp;
}
//numの値が同じ場合はstrを比較する
return this.str.compareTo(another.str);
}
}自作クラスをソートしたい場合は、インターフェースであるComparebleのcompareTo()を実装します。
compareTo()は、自身と引数を比較した時に、大きければ正の値、小さければ負の値、同じであれば 0 になるように実装します。
これによってsort()は、並び替えの条件を判断しています。
上の例の昇順ソートは下記のようになります。
{ num: 0, str: "CCC" },
{ num: 1, str: "ABC" },
{ num: 1, str: "BAC" },
{ num: 2, str: "000" },
{ num: 2, str: "ABC" },IntegerとStringにはあらかじめComparableが実装されているためソートが実行されていました。
Comparator によるソート
Comparatorによるソートは、Comparableで定義したものとは違うルールでソートしたい場合に使用します。
例えば、先程のMyClassのソートをnum, strの順ではなく、str, numの順でソートしたいとします。
List<MyClass> list = new ArrayList<>();
list.add(new MyClass(1, "ABC"));
list.add(new MyClass(2, "ABC"));
list.add(new MyClass(1, "BAC"));
list.add(new MyClass(0, "CCC"));
list.add(new MyClass(2, "000"));
//ソートの定義
Comparator comparator = new Comparator<MyClass>() {
@Override
public int compare(MyClass a, MyClass b) {
int cmp = 0;
if ((cmp = a.str.compareTo(b.str)) != 0) {
return cmp;
}
return a.num - b.num;
}
}
//昇順ソート
Collections.sort(list, comparator);
//降順ソート
Collections.sort(list, comparator.reversed());例のように無名クラスとしてComparatorのcompare()を実装します。
compare()の実装は、ComparableのcompareTo()を同じ考え方です。
これによって昇順ソートは下記のようになります。
{ num: 2, str: "000" },
{ num: 1, str: "ABC" },
{ num: 2, str: "ABC" },
{ num: 1, str: "BAC" },
{ num: 0, str: "CCC" },