java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

オブジェクト配列のソート

投稿日:

最終更新日:2016年07月20日

アイキャッチ

こんにちは。「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」という記述だけで十分になります。型の類推もしてくれるようです。