Javaで自作クラスのリストを2変数以上でソートする方法
はじめに
この記事では、Javaを用いて、自作クラスのリストをソートする方法について書きます。
方法はいくつかありますが、一番簡単な方法を1つ紹介します。
1変数の場合
例えば3つの変数を持つレコードのリストを1変数でソートする場合は、java.util.Comparatorのcomparing関数を使用してcomparatorというものを作り出し、それを元にソートします。
詳細はJavaのリファレンスを参考にしてください。
以下の例では、Personというレコードのageという変数に着目して、リストをソートしています。
import java.util.*;
public class Main {
public static void main(String[] args) {
var persons = new ArrayList<Person>();
persons.add(new Person(23, 172, "山田"));
persons.add(new Person(35, 164, "佐藤"));
persons.add(new Person(32, 178, "井上"));
persons.add(new Person(32, 154, "村山"));
System.out.println("ソート前");
persons.forEach(System.out::println);
System.out.println("----------");
var comparator = Comparator.comparing(Person::age);
persons.sort(comparator);
System.out.println("ソート後");
persons.forEach(System.out::println);
}
record Person(Integer age, Integer height, String name) {
}
}
この出力結果は以下の通りです。
ソート前
Person[age=23, height=172, name=山田]
Person[age=35, height=164, name=佐藤]
Person[age=32, height=178, name=井上]
Person[age=32, height=154, name=村山]
----------
ソート後
Person[age=23, height=172, name=山田]
Person[age=32, height=178, name=井上]
Person[age=32, height=154, name=村山]
Person[age=35, height=164, name=佐藤]
これで年齢(age)の昇順でリストが並ぶようになりました。
しかし当然ですが、身長(height)までは昇順になっていません。32歳は村山さんと井上さんの2名がいますが、身長の高い井上さんが前に来てしまっている状況です。
年齢だけでなく身長も昇順に並べたい場合はどうすれば良いでしょうか。
2変数の場合
ageとheightの2変数でソートをかけたい場合、以下のようにthenComparing関数を1変数の時のcomparatorの後ろに付けましょう。
import java.util.*;
public class Main {
public static void main(String[] args) {
var persons = new ArrayList<Person>();
persons.add(new Person(23, 172, "山田"));
persons.add(new Person(35, 164, "佐藤"));
persons.add(new Person(32, 178, "井上"));
persons.add(new Person(32, 154, "村山"));
System.out.println("ソート前");
persons.forEach(System.out::println);
System.out.println("----------");
var comparator = Comparator.comparing(Person::age).thenComparing(Person::height);
persons.sort(comparator);
System.out.println("ソート後");
persons.forEach(System.out::println);
}
record Person(Integer age, Integer height, String name) {
}
}
出力結果は以下のようになります。
ソート前
Person[age=23, height=172, name=山田]
Person[age=35, height=164, name=佐藤]
Person[age=32, height=178, name=井上]
Person[age=32, height=154, name=村山]
----------
ソート後
Person[age=23, height=172, name=山田]
Person[age=32, height=154, name=村山]
Person[age=32, height=178, name=井上]
Person[age=35, height=164, name=佐藤]
これで年齢と身長の両方でソートできるようになり、井上さんと村山さんが身長の昇順で並ぶようになりました。
3変数以上のソートも2変数と同様に、thenComparingを増やしていけば良いだけです。これで自作クラスについての基本的なソートはできるはずです。
おまけ: 降順にしたい場合
おまけで、降順にしたい場合について解説します。
例えば先ほどのPersonというレコードのリストについて、年齢の降順で並べたい場合、以下のようにcomparing関数の第2引数にjava.util.CollectionsのreverseOrder関数を入れましょう。
import java.util.*;
public class Main {
public static void main(String[] args) {
var persons = new ArrayList<Person>();
persons.add(new Person(23, 172, "山田"));
persons.add(new Person(35, 164, "佐藤"));
persons.add(new Person(32, 178, "井上"));
persons.add(new Person(32, 154, "村山"));
System.out.println("ソート前");
persons.forEach(System.out::println);
System.out.println("----------");
var comparator = Comparator.comparing(Person::age, Collections.reverseOrder());
persons.sort(comparator);
System.out.println("ソート後");
persons.forEach(System.out::println);
}
record Person(Integer age, Integer height, String name) {
}
}
出力結果はこのようになります。
ソート前
Person[age=23, height=172, name=山田]
Person[age=35, height=164, name=佐藤]
Person[age=32, height=178, name=井上]
Person[age=32, height=154, name=村山]
----------
ソート後
Person[age=35, height=164, name=佐藤]
Person[age=32, height=178, name=井上]
Person[age=32, height=154, name=村山]
Person[age=23, height=172, name=山田]
年齢の降順に並ぶようになりました。
おわりに
自作クラスのソート方法についてまとめました。
Javaで自作クラスのソートをやろうとすると、例えばInteger型のリストのソートと同じやり方ではできず、意外な盲点となりがちです。しかし、業務などでプログラミングをする場合は、基本的に自作クラスのソートになると思うので、この記事で紹介したソートの方法を使う場合が多くなると思います。こちらのソート方法も覚えておきましょう。
Discussion