![]()
【Java入門 実用編】List のソートと Comparator | コレクションクラスの活用
2025.12.19
実務でJavaを利用する場合、画面表示やデータ加工のために List の要素を並び替える「ソート処理」が必要となるケースはよくあります。
ソートは単純な処理である一方、Collections.sort を使う方法から、Stream API による直感的な記述まで、用途に応じた方法が準備されているポイントでもあります。
本記事では、最初の一歩として基本となるソートの方法についてご紹介します。
目次
基本的なソートの方法
Javaでリストを並び替える(ソートする)基本的な方法として、レガシーなユーティリティクラスの Collections.sort メソッドを使う方法と、リストのクラス自身が持っている List.sort メソッドを使う方法があります。
Collections.sort メソッドと List.sort メソッド
現在ではより直感的に記述可能な List.sort の利用が推奨されており、Collections.sort が利用される機会は減っていますが、既存のソースを理解するために必要となるケースも想定し、両者の違いは知っておきたいところです。
まず、List.sort、Collections.sort のいずれの場合も、対象の List そのものの要素をソートすることに注意が必要です。元の List の要素の並びはそのままに、別の List にソートして格納したい場合は利用できません。
いずれのメソッドも比較順の指定には「Comparator インターフェイス」を用います。特に、数値や文字列のように単純な比較を行う場合は Comparator インターフェースのメソッドを使って順序(昇順・降順)を指定できます。
このとき、List.sort では必ず引数に Comparator の指定が必要となるのに対し、Collections.sort の場合は自然順序(昇順)の場合 Comparator の指定が省略可能であることに注意してください。
まず、文字列(String)のリストをソートしてみましょう。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SortComparisonExample {
public static void main(String[] args) {
// 比較のために同じ内容のリストを2つ用意
List<String> listOld = new ArrayList<>();
listOld.add("Banana");
listOld.add("Apple");
listOld.add("Cherry");
// listNew に listOld の内容をコピー
List<String> listNew = new ArrayList<>(listOld);
System.out.println("--- 1. 昇順(A → Z)の比較 ---");
// 【Old】 Collections.sort を利用
// 引数が1つの場合は自然順序(昇順)になる
Collections.sort(listOld);
System.out.println("Old style: " + listOld);
// 【New】 List.sort を利用
// Comparator.naturalOrder() で明示的に自然順序を指定
listNew.sort(Comparator.naturalOrder());
System.out.println("New style: " + listNew);
System.out.println("\n--- 2. 降順(Z → A)の比較 ---");
// 【Old】 Collections.sort を利用
// 第2引数に Collections.reverseOrder() を渡す
Collections.sort(listOld, Collections.reverseOrder());
System.out.println("Old style: " + listOld);
// 【New】 List.sort を利用
// 引数に Comparator.reverseOrder() を渡す
listNew.sort(Comparator.reverseOrder());
System.out.println("New style: " + listNew);
}
}
実行結果:
--- 1. 昇順(A → Z)の比較 ---
Old style: [Apple, Banana, Cherry]
New style: [Apple, Banana, Cherry]
--- 2. 降順(Z → A)の比較 ---
Old style: [Cherry, Banana, Apple]
New style: [Cherry, Banana, Apple]
次に、数値のリストで同じように実行してみます。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class NumberComparisonExample {
public static void main(String[] args) {
// 比較のために同じ内容のリストを2つ用意
List<Integer> listOld = new ArrayList<>(List.of(10, 5, 20, 8));
List<Integer> listNew = new ArrayList<>(listOld);
System.out.println("--- 1. 昇順(小さい順)の比較 ---");
// 【Old】 Collections.sort を利用
// 引数が1つの場合は自然順序(昇順)になる(Comparator省略可)
Collections.sort(listOld);
System.out.println("Collections.sort: " + listOld);
// 【New】 List.sort を利用
// Comparator.naturalOrder() で明示的に自然順序を指定する(引数必須)
listNew.sort(Comparator.naturalOrder());
System.out.println("List.sort : " + listNew);
System.out.println("\n--- 2. 降順(大きい順)の比較 ---");
// 【Old】 Collections.sort を利用
// 第2引数に Collections.reverseOrder() を渡す
Collections.sort(listOld, Collections.reverseOrder());
System.out.println("Collections.sort: " + listOld);
// 【New】 List.sort を利用
// 引数に Comparator.reverseOrder() を渡す
listNew.sort(Comparator.reverseOrder());
System.out.println("List.sort : " + listNew);
}
}
実行結果:
--- 1. 昇順(小さい順)の比較 ---
Collections.sort: [5, 8, 10, 20]
List.sort : [5, 8, 10, 20]
--- 2. 降順(大きい順)の比較 ---
Collections.sort: [20, 10, 8, 5]
List.sort : [20, 10, 8, 5]Comparator の利用
オブジェクトのソート(単一条件)
独自の Java Bean クラスなどのオブジェクトのリストの場合、数値や文字列とは異なり、Java が自動的に順序を判断することができません。そのため、「どの項目(フィールド)で並び替えるか」を明示的に指定する必要があります。
このような場合、Comparator.comparing メソッドを使用できます。このメソッドを使うことで、「User クラスの age(年齢)フィールドで比較する」といった独自の指定を、メソッド参照(::)を用いて簡潔に記述できます。
まず、メンバーに name(文字列)と age(int)を持つ bean クラス User があるとします。
public class User {
String name;
int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// 結果を見やすくするためにtoStringをオーバーライド
@Override
public String toString() {
return name + "(" + age + ")";
}
// age の getterメソッド
public int getAge() { return age; }
// name の getterメソッド
public String getName() { return name; }
}
この User を複数格納した List に対して、List.sort メソッドと Comparator.comparing メソッドを利用し User の年齢を利用順にソートします。
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class ObjectSortExample {
public static void main(String[] args) {
List<User> users = new ArrayList<>();
users.add(new User("Tanaka", 25));
users.add(new User("Suzuki", 20));
users.add(new User("Sato", 30));
System.out.println("元のリスト: " + users);
// 【昇順】 年齢(age)でソート
// 「UserクラスのgetAgeメソッドの値」を使って比較する
users.sort(Comparator.comparing(User::getAge));
System.out.println("年齢昇順 : " + users);
// 【降順】 年齢(age)でソート(reversedを利用)
// 最後に reversed メソッドで順序を反転
users.sort(Comparator.comparing(User::getAge).reversed());
System.out.println("年齢降順 : " + users);
}
}
実行結果:
元のリスト: [Tanaka(25), Suzuki(20), Sato(30)]
年齢昇順 : [Suzuki(20), Tanaka(25), Sato(30)]
年齢降順 : [Sato(30), Tanaka(25), Suzuki(20)]
ここでは、年齢の昇順でソートをしているため、昇順、降順の指定を省略していますが、comparing メソッドの引数で明示的に順序を指定することもできます。
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class ObjectSortExample2 {
public static void main(String[] args) {
List<User> users = new ArrayList<>();
users.add(new User("Tanaka", 25));
users.add(new User("Suzuki", 20));
users.add(new User("Sato", 30));
System.out.println("元のリスト: " + users);
// 【昇順】 年齢(age)でソート
// Comparator.naturalOrder を指定
users.sort(Comparator.comparing(User::getAge, Comparator.naturalOrder()));
System.out.println("年齢昇順 : " + users);
// 【降順】 年齢(age)でソート
// Comparator.reverseOrder を指定
users.sort(Comparator.comparing(User::getAge, Comparator.reverseOrder()));
System.out.println("年齢降順 : " + users);
}
}オブジェクトのソート(複数条件)
Comparator をメソッドチェーン(鎖のように繋げて書く方法)として記述することで、複数の条件を指定したソートを行うこともできます。
具体的には、Comparator.thenComparing メソッドを利用することで、「年齢順に並べたいが、もし年齢が同じだった場合は、名前順(あいうえお順)に並べたい」というように、優先順位をつけて複数の条件を指定することが可能です。
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class MultiSortExample {
public static void main(String[] args) {
List<User> users = new ArrayList<>();
users.add(new User("Tanaka", 25));
users.add(new User("Suzuki", 25));
users.add(new User("Ando", 20));
System.out.println("元のリスト: " + users);
// 【複数条件ソート】
// 1. まず年齢(Age)で比較
// 2. 年齢が同じなら、名前(Name)で比較
users.sort(Comparator.comparing(User::getAge)
.thenComparing(User::getName));
System.out.println("ソート結果: " + users);
}
}
実行結果:
元のリスト: [Tanaka(25), Suzuki(25), Ando(20)]
ソート結果: [Ando(20), Suzuki(25), Tanaka(25)]
thenComparing メソッドも、第二引数で昇順、降順の指定をすることが可能です。以下の例のように、年齢を降順、名前を昇順に指定することもできます。
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class MultiSortExample {
public static void main(String[] args) {
List<User> users = new ArrayList<>();
users.add(new User("Tanaka", 25));
users.add(new User("Suzuki", 25));
users.add(new User("Ando", 20));
System.out.println("元のリスト: " + users);
// 【複数条件ソート】
// 1. まず年齢(Age)の降順で比較
// 2. 年齢が同じなら、名前(Name)の昇順で比較
users.sort(Comparator.comparing(User::getAge, Comparator.reverseOrder())
.thenComparing(User::getName, Comparator.naturalOrder()));
System.out.println("ソート結果: " + users);
}
}
実行結果:
元のリスト: [Tanaka(25), Suzuki(25), Ando(20)]
ソート結果: [Suzuki(25), Tanaka(25), Ando(20)]
この thenComparing メソッドは、何度も繰り返してつなげることができるため、もっと複雑なソート順序が必要な場合でも対応することができます。
本記事では、Collections.sort および List.sort メソッドを利用した基本的なソート方法についてご説明しましたが、いかがでしたでしょうか。次回の記事では、Stream API を利用したソート手順について説明します。



