自然順序付け(Comparable) — デフォルトソート
Java の「自然順序付け」は、クラスが Comparable インターフェースを実装している場合に使われる「デフォルトの並び替えルール」です。Collections.sort や Arrays.sort、TreeSet や TreeMap などで自動的に利用されます。
基本の考え方
- Comparable インターフェース:
public interface Comparable<T> { int compareTo(T o); }compareToメソッドで「自分と相手の大小」を返す。- 戻り値の意味:
- 負の値 → 自分が相手より「小さい」
- 0 → 等しい
- 正の値 → 自分が相手より「大きい」
- 自然順序:
- 数値 → 小さい順
- 文字列 → 辞書順(アルファベット順)
- 日付 → 古い順
👉 これらはすでに Comparable を実装済みなので、そのままソートできる。
基本コード例
1. 数値の自然順序
import java.util.*;
public class NaturalOrderDemo {
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(5, 2, 9, 1);
Collections.sort(nums); // Comparable に基づく昇順
System.out.println(nums); // [1, 2, 5, 9]
}
}
Java2. 文字列の自然順序
List<String> words = Arrays.asList("banana", "apple", "cherry");
Collections.sort(words);
System.out.println(words); // [apple, banana, cherry]
Java独自クラスで Comparable を実装
例: ユーザークラスを年齢昇順で並べる
class User implements Comparable<User> {
String name;
int age;
User(String name, int age) {
this.name = name; this.age = age;
}
@Override
public int compareTo(User other) {
return Integer.compare(this.age, other.age); // 年齢昇順
}
@Override
public String toString() {
return name + "(" + age + ")";
}
}
public class Main {
public static void main(String[] args) {
List<User> users = Arrays.asList(
new User("Tanaka", 30),
new User("Sato", 25),
new User("Kato", 40)
);
Collections.sort(users); // 年齢昇順
System.out.println(users); // [Sato(25), Tanaka(30), Kato(40)]
}
}
Java例題で練習
例題1: 書籍をタイトル昇順で並べる
class Book implements Comparable<Book> {
String title;
Book(String title) { this.title = title; }
@Override
public int compareTo(Book other) {
return this.title.compareTo(other.title); // 文字列の自然順序
}
@Override
public String toString() { return title; }
}
List<Book> books = Arrays.asList(new Book("Java"), new Book("Python"), new Book("C++"));
Collections.sort(books);
System.out.println(books); // [C++, Java, Python]
Java例題2: 日付の自然順序
import java.time.LocalDate;
import java.util.*;
List<LocalDate> dates = Arrays.asList(
LocalDate.of(2025, 12, 9),
LocalDate.of(2024, 5, 1),
LocalDate.of(2026, 1, 1)
);
Collections.sort(dates); // 古い順
System.out.println(dates); // [2024-05-01, 2025-12-09, 2026-01-01]
Java例題3: TreeSet に自然順序で格納
Set<String> set = new TreeSet<>();
set.add("banana");
set.add("apple");
set.add("cherry");
System.out.println(set); // [apple, banana, cherry]
Javaテンプレート集
- Comparable 実装の基本形
class MyClass implements Comparable<MyClass> {
private int key;
@Override
public int compareTo(MyClass other) {
return Integer.compare(this.key, other.key);
}
}
Java- 文字列比較
return this.name.compareTo(other.name);
Java- 複合キー比較(主キー→副キー)
int cmp = Integer.compare(this.age, other.age);
if (cmp != 0) return cmp;
return this.name.compareTo(other.name);
Java実務でのコツ
- 自然順序を定義するのは「そのクラスの標準的な並び」
→ 例えば「User は年齢昇順が自然」と決めるなら Comparable に書く。 - 複数の並び替えが必要なら Comparator を使う
→ Comparable は 1 つの順序しか定義できない。別の順序が必要ならComparatorを渡す。 - compareTo の実装は安全な比較メソッドを使う
→a - bはオーバーフローの危険。Integer.compare/Double.compareを使う。 - equals と整合性: compareTo が 0 を返す場合は equals も true になるように設計するのが望ましい。
まとめ
- Comparable は「自然順序」を定義するインターフェース。
- 数値・文字列・日付はすでに Comparable 実装済みなので、そのままソート可能。
- 独自クラスは compareTo を実装して「標準的な並び」を決める。
- 複数の並び替えが必要なら Comparator を併用する。
👉 練習課題として「学生クラスを学籍番号昇順で Comparable 実装し、同点なら名前昇順にする」プログラムを書いてみると、自然順序付けの理解が深まります。
