Java 逆引き集 | 自然順序付け(Comparable) — デフォルトソート

Java Java
スポンサーリンク

自然順序付け(Comparable) — デフォルトソート

Java の「自然順序付け」は、クラスが Comparable インターフェースを実装している場合に使われる「デフォルトの並び替えルール」です。
Collections.sortArrays.sortTreeSetTreeMap などで自動的に利用されます。


基本の考え方

  • 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]
    }
}
Java

2. 文字列の自然順序

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 実装し、同点なら名前昇順にする」プログラムを書いてみると、自然順序付けの理解が深まります。

タイトルとURLをコピーしました