コレクションのソートは「並び順というビジネスルール」をコードにする作業
ソートは単なる「小さい順・大きい順」ではありません。
業務では「名前の五十音順」「日付の新しい順」「ステータス順(独自の優先度)」など、
ビジネスルールそのものが「並び順」として現れます。
だからこそ、ソートは「アルゴリズムの話」よりも
「どんな順番にしたいのかを、分かりやすくコードに書く」ことが重要になります。
基本の List ソートを押さえる
Collections.sort と List.sort の違い
まずは一番基本の「昇順ソート」です。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SortBasic {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>();
numbers.add(3);
numbers.add(1);
numbers.add(2);
Collections.sort(numbers); // 昇順に並び替え
System.out.println(numbers); // [1, 2, 3]
}
}
JavaJava 8 以降なら、List#sort もよく使います。
numbers.sort(Integer::compareTo);
Javaどちらも「元の List をその場で並び替える」点が重要です。
つまり、ソートは“破壊的操作”です。
業務では「元の順番も必要」「ソート後の順番も必要」ということがよくあるので、
その場合は先にコピーを作ってからソートするのが安全です。
List<Integer> sorted = new ArrayList<>(numbers);
Collections.sort(sorted);
Javaここでの大事な感覚は、
「ソートは元のデータを変える操作なので、コピーするかどうかを意識する」ことです。
Comparator で「並び順のルール」に名前をつける
文字列を昇順・降順に並べる
Comparator を使うと、「どう並べるか」を柔軟に指定できます。
import java.util.Comparator;
import java.util.List;
public class SortString {
public static void main(String[] args) {
List<String> names = new java.util.ArrayList<>(
List.of("山田", "佐藤", "鈴木")
);
// 昇順(自然順)
names.sort(Comparator.naturalOrder());
System.out.println(names); // [佐藤, 山田, 鈴木] など
// 降順
names.sort(Comparator.reverseOrder());
System.out.println(names); // [鈴木, 山田, 佐藤] など
}
}
Javaここでのポイントは、「Comparator は“並び順のルール”そのもの」ということです。
業務でよく出てくる「独自の順番」も、Comparator に閉じ込めると読みやすくなります。
オブジェクトを特定の項目でソートする
例えば、ユーザーを「年齢の昇順」で並べたいとします。
class User {
private final String name;
private final int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
Javaこれをソートするコードはこう書けます。
import java.util.Comparator;
import java.util.List;
public class SortUser {
public static void main(String[] args) {
List<User> users = new java.util.ArrayList<>(
List.of(
new User("山田", 30),
new User("佐藤", 25),
new User("鈴木", 40)
)
);
users.sort(Comparator.comparingInt(User::getAge));
for (User u : users) {
System.out.println(u.getName() + " " + u.getAge());
}
// 佐藤 25
// 山田 30
// 鈴木 40
}
}
Javaここでの重要ポイントは、「Comparator.comparingInt(User::getAge)」という一行が
「年齢の昇順で並べる」というビジネスルールをそのまま表していることです。
複数条件ソートで「業務っぽい順番」を表現する
まず年齢昇順、同じなら名前昇順
業務では「まずこれで並べて、同じならこれで…」という複数条件ソートがよく出てきます。
Comparator はそれをとても素直に書けます。
users.sort(
Comparator.comparingInt(User::getAge)
.thenComparing(User::getName)
);
Javaこの一行で、
「年齢の昇順、年齢が同じなら名前の昇順」というルールを表現できます。
コードを読む人は、if 文を追いかけなくても、
「どういう順番なのか」を一目で理解できます。
ここが、Comparator を“業務ルールの言語”として使ううえで、非常に大事なポイントです。
null を含むデータをソートするときの注意点
null を先頭・末尾に寄せる Comparator
現実のデータには、よく null が混ざります。
そのままソートすると NullPointerException になることもあります。
Comparator には、null を安全に扱うためのヘルパーがあります。
import java.util.Comparator;
Comparator<String> byNameNullsLast =
Comparator.nullsLast(Comparator.naturalOrder());
Comparator<String> byNameNullsFirst =
Comparator.nullsFirst(Comparator.naturalOrder());
Java使い方のイメージです。
List<String> names = new java.util.ArrayList<>(
List.of("山田", null, "佐藤")
);
names.sort(Comparator.nullsLast(Comparator.naturalOrder()));
System.out.println(names); // [佐藤, 山田, null] など
Javaここでの重要ポイントは、「null をどう扱うかも“並び順のルール”の一部」だということです。
「null は最後に寄せる」「null は先頭に寄せる」「そもそも null は許さない」
どれを選ぶかを、Comparator で明示しておくと、後から読んだ人にも意図が伝わります。
不変リストとソートの組み合わせ方
「ソート済みの不変リスト」をユーティリティで作る
List.of(...) や List.copyOf(...) で作った不変リストは、そのままではソートできません。
業務では「ソート済みの不変リスト」が欲しいことも多いので、
ユーティリティでまとめてしまうと便利です。
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public final class SortedLists {
private SortedLists() {}
public static <T> List<T> sorted(List<T> source, Comparator<? super T> comparator) {
if (source == null || source.isEmpty()) {
return List.of();
}
List<T> copy = new ArrayList<>(source);
copy.sort(comparator);
return List.copyOf(copy); // ソート済み不変リスト
}
}
Java使い方はこうです。
List<String> raw = List.of("B", "A", "C");
List<String> sorted =
SortedLists.sorted(raw, Comparator.naturalOrder());
System.out.println(sorted); // [A, B, C]
// sorted.add("X"); // UnsupportedOperationException
Javaここでの重要ポイントは、「ソートと不変化をセットで扱っている」ことです。
「このリストはこの順番で固定」という意図を、
型と実装で表現できます。
まとめ:ソートユーティリティで身につけてほしい感覚
ソートは、単に「小さい順に並べるテクニック」ではなく、
「ビジネス上の並び順を、Comparator という形でコードに刻む」 作業です。
元の List を壊すかどうかを意識し、必要ならコピーしてからソートする。
Comparator を使って、「何で並べるか」「昇順か降順か」「同値のときどうするか」を明示する。
複数条件ソートや null の扱いも、Comparator でルールとして書き下す。
必要なら「ソート済み不変リスト」を返すユーティリティを用意し、「この順番で固定」という意図を表現する。
あなたが書くソートコードが、
「アルゴリズム」ではなく「業務ルールの宣言」に見えるようになってきたら、
それはもう立派に“実務で使えるソートユーティリティ”を扱えている状態です。

