こんにちは。「Javaを復習する初心者」です。
今回はオブジェクトの配列をソートする方法について書こうと思います。
使うメソッド
前回はint型の配列をArrays.sortメソッドでソートしました。順番は昇順です。int型なので数値の大小関係でソートしてくれます。
オブジェクト型のソートの場合は以下のメソッドを使います。
- static <T> void sort(T[] a, Comparator<? super T> c)
第2引数が大小関係を定義するクラスになります。Comparatorはインターフェースであるため、Comparatorを実装したクラスを第2引数に指定します。このインターフェースの定義を抜粋すると以下になります。
ソースコード
public interface Comparator<T> {
int compare(T o1, T o2);
.
.
.
}
返却するintの値は以下のようにします。
順序関係 | 返却値 |
---|---|
o1がo2より小さい | 負の数 |
o1とo2が等しい | 0 |
o1がo2より大きい | 正の数 |
このようなComparatorの実装クラスを用意することになります。
Comparatorの実装クラスを定義
今回はソートする対象となるMyObjクラスを定義しました。String型変数nameとint型ageをフィールドに持ちます。このクラスのインスタンスを生成し、ageにランダムな値を設定して、ageで昇順で並べ替えるサンプルを作りました。
以下はソースと実行結果です。
ソース
package arraysTest;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;
public class SortObj {
public static void main(String[] args) {
Random random = new Random();
MyObj[] myObjs = new MyObj[5];
myObjs[0] = new MyObj("test1", random.nextInt(100));
myObjs[1] = new MyObj("test2", random.nextInt(100));
myObjs[2] = new MyObj("test3", random.nextInt(100));
myObjs[3] = new MyObj("test4", random.nextInt(100));
myObjs[4] = new MyObj("test5", random.nextInt(100));
System.out.println("ソート前");
for (MyObj o : myObjs) {
System.out.println(o.name + " " + o.age);
}
Arrays.sort(myObjs, new MyObjComp());
System.out.println("ソート後");
for (MyObj o : myObjs) {
System.out.println(o.name + " " + o.age);
}
}
}
class MyObj {
public String name;
public int age;
public MyObj(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
class MyObjComp implements Comparator<MyObj> {
@Override
public int compare(MyObj o1, MyObj o2) {
// o1の方が昇順で上なら負の数を返す。
return o1.age - o2.age;
}
}
結果
ソート前
test1 6
test2 60
test3 25
test4 2
test5 14
ソート後
test4 2
test1 6
test5 14
test3 25
test2 60
Comparatorインターフェース
上記サンプルは、Comparatorの実装クラスを定義してArrays.sortメソッドの第2引数に指定していますが、匿名クラスで渡すこともできます。また、Comparatorインターフェースは@FunctionalInterfaceがついているため、ラムダ式も使えます。ラムダ式を使った例が以下になります。
ソース
package arraysTest;
import java.util.Arrays;
import java.util.Random;
public class SortObjLambda {
public static void main(String[] args) {
Random random = new Random();
MyObj[] myObjs = new MyObj[5];
myObjs[0] = new MyObj("test1", random.nextInt(100));
myObjs[1] = new MyObj("test2", random.nextInt(100));
myObjs[2] = new MyObj("test3", random.nextInt(100));
myObjs[3] = new MyObj("test4", random.nextInt(100));
myObjs[4] = new MyObj("test5", random.nextInt(100));
System.out.println("ソート前");
for (MyObj o : myObjs) {
System.out.println(o.name + " " + o.age);
}
Arrays.sort(myObjs, (a, b) -> a.age - b.age);
System.out.println("ソート後");
for (MyObj o : myObjs) {
System.out.println(o.name + " " + o.age);
}
}
}
今回の場合、フィールドageの差のみをreturnすればよいため、「(a, b) -> a.age – b.age」という記述だけで十分になります。型の類推もしてくれるようです。