Comparator と Comparable

JavaBeginner
オンラインで実践に進む

はじめに

Java アプリケーションでは、オブジェクトの比較や並べ替えが必要になることがよくあります。整数や文字列などのプリミティブデータ型については、Java はそれらの比較方法を既に知っています。しかし、カスタムオブジェクトの場合、Java にそれらの比較方法や順序付け方法を教える必要があります。

Java では、この問題を解決するために 2 つのインターフェースが用意されています。

  • Comparable インターフェースは、クラスが自然な順序付けを定義することを可能にします。
  • Comparator インターフェースは、さまざまな並べ替え基準に使用できる外部の比較ロジックを提供します。

この実験では、これらのインターフェースをどのように実装し、オブジェクトのコレクションをさまざまな方法で並べ替えるために使用するかを学びます。

Comparable インターフェースの理解

Comparable インターフェースは、クラスに自然な順序付けがある場合に使用されます。たとえば、文字列は自然にアルファベット順で並べられ、整数は自然に数値順で並べられます。

クラスが Comparable インターフェースを実装する場合、そのクラスのインスタンスをどのように順序付けるかを指定する compareTo() メソッドを定義する必要があります。

基本的な Student クラスの作成

Comparable インターフェースの使い方を示すために、簡単な Student クラスを作成しましょう。学生を名前、GPA(平均成績点)、登録番号で定義します。

  1. WebIDE を開き、~/project ディレクトリに Student.java という名前の新しいファイルを作成し、以下のコードを記述します。
public class Student implements Comparable<Student> {
    private String name;
    private double gpa;
    private int regNo;

    public Student(String name, double gpa, int regNo) {
        this.name = name;
        this.gpa = gpa;
        this.regNo = regNo;
    }

    // Implementing the compareTo method from Comparable interface
    @Override
    public int compareTo(Student other) {
        // Compare students based on GPA
        if (this.gpa < other.gpa) {
            return -1;
        } else if (this.gpa > other.gpa) {
            return 1;
        } else {
            return 0;
        }
    }

    // Getters
    public String getName() {
        return name;
    }

    public double getGpa() {
        return gpa;
    }

    public int getRegNo() {
        return regNo;
    }

    @Override
    public String toString() {
        return name + ", GPA: " + gpa + ", Reg No: " + regNo;
    }
}

このコードを理解しましょう。

  • Student クラスは Comparable<Student> インターフェースを実装しています。
  • compareTo() メソッドは、学生を GPA を基準に比較します。
  • 現在の学生の GPA が他の学生の GPA より低い場合、-1 を返します。
  • 現在の学生の GPA が他の学生の GPA より高い場合、1 を返します。
  • GPA が等しい場合、0 を返します。

では、Comparable インターフェースを使って学生を並べ替える方法を確認するために、簡単なテストプログラムを作成しましょう。

  1. ~/project ディレクトリに ComparableDemo.java という名前の新しいファイルを作成し、以下のコードを記述します。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparableDemo {
    public static void main(String[] args) {
        // Create a list of students
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.2, 103));
        students.add(new Student("Bob", 3.9, 104));

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort the list using the natural ordering (defined by compareTo method)
        Collections.sort(students);

        // Print the sorted list
        System.out.println("\nStudents sorted by GPA (using Comparable):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

このプログラムは以下のことを行います。

  1. Student オブジェクトのリストを作成します。

  2. ソートされていないリストを出力します。

  3. Collections.sort() を使ってリストをソートします。このメソッドは compareTo() メソッドで定義された自然な順序付けを使用します。

  4. ソートされたリストを出力します。

  5. では、コードをコンパイルして実行し、出力を確認しましょう。

cd ~/project
javac Student.java ComparableDemo.java
java ComparableDemo

以下のような出力が表示されるはずです。

Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104

Students sorted by GPA (using Comparable):
Alice, GPA: 3.2, Reg No: 103
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Bob, GPA: 3.9, Reg No: 104

ご覧のとおり、学生は GPA の昇順で並べ替えられています。これは compareTo() メソッドで定義した自然な順序付けです。

Comparator の作成と使用

Comparable インターフェースはクラスの自然な順序付けを定義しますが、時には異なる基準でオブジェクトを並べ替える必要があります。このような場合に Comparator インターフェースが役立ちます。

Comparator インターフェースを使用すると、比較対象のクラスとは別にカスタムの順序付けロジックを定義できます。これにより、同じクラスのオブジェクトを複数の方法で並べ替えることが可能になります。

名前でのソート用のコンパレータの作成

学生を名前のアルファベット順で並べ替える Comparator を作成しましょう。

  1. ~/project ディレクトリに StudentNameComparator.java という名前の新しいファイルを作成し、以下のコードを記述します。
import java.util.Comparator;

public class StudentNameComparator implements Comparator<Student> {
    @Override
    public int compare(Student s1, Student s2) {
        // Compare students based on their names
        return s1.getName().compareTo(s2.getName());
    }
}

この Comparator は以下のように動作します。

  • Comparator<Student> インターフェースを実装しています。
  • 2 つの Student オブジェクトを引数に取る compare() メソッドを定義しています。
  • String クラスの compareTo() メソッドを使用して、学生を名前で比較します。
  1. この Comparator の使い方を示すプログラムを作成しましょう。~/project ディレクトリに ComparatorDemo.java という名前のファイルを作成します。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparatorDemo {
    public static void main(String[] args) {
        // Create a list of students
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.2, 103));
        students.add(new Student("Bob", 3.9, 104));

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort by name using the StudentNameComparator
        Collections.sort(students, new StudentNameComparator());

        // Print the list sorted by name
        System.out.println("\nStudents sorted by name (using Comparator):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

このプログラムは以下のことを行います。

  1. Student オブジェクトのリストを作成します。

  2. ソートされていないリストを出力します。

  3. カスタムの StudentNameComparator を使用して Collections.sort() でリストをソートします。

  4. ソートされたリストを出力します。

  5. コードをコンパイルして実行しましょう。

cd ~/project
javac Student.java StudentNameComparator.java ComparatorDemo.java
java ComparatorDemo

以下のような出力が表示されるはずです。

Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104

Students sorted by name (using Comparator):
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102

ご覧のとおり、学生は GPA ではなく名前のアルファベット順で並べ替えられています。

ラムダ式を使用したコンパレータの作成

Java 8 で導入されたラムダ式を使用すると、コンパレータの作成を簡素化できます。別のクラスを作成する代わりに、比較ロジックをインラインで定義できます。

  1. ~/project ディレクトリに LambdaComparatorDemo.java という名前の新しいファイルを作成します。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class LambdaComparatorDemo {
    public static void main(String[] args) {
        // Create a list of students
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.2, 103));
        students.add(new Student("Bob", 3.9, 104));

        // Sort by registration number using lambda expression
        Collections.sort(students, (s1, s2) -> s1.getRegNo() - s2.getRegNo());

        // Print the list sorted by registration number
        System.out.println("Students sorted by registration number (using lambda):");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort by name using method reference
        Collections.sort(students, Comparator.comparing(Student::getName));

        // Print the list sorted by name
        System.out.println("\nStudents sorted by name (using method reference):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

このプログラムは以下のことを示しています。

  1. ラムダ式を使用して、学生を登録番号で並べ替えるコンパレータを作成します。

  2. Comparator.comparing() メソッドとメソッド参照を使用して、学生を名前で並べ替えるコンパレータを作成します。

  3. このコードをコンパイルして実行します。

cd ~/project
javac Student.java LambdaComparatorDemo.java
java LambdaComparatorDemo

以下のような出力が表示されるはずです。

Students sorted by registration number (using lambda):
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104

Students sorted by name (using method reference):
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102

学生はまず登録番号で、次に名前で並べ替えられています。

高度なソート技術

実際のアプリケーションでは、より複雑なソートロジックが必要になることがよくあります。例えば以下のようなものです。

  • 複数の基準でソートする(例:GPA でソートし、GPA が同じ場合は名前でソートする)
  • 逆順でソートする
  • カスタムのコンパレータチェーンを作成する

これらの高度な技術を探ってみましょう。

複数の基準でソートする

  1. ~/project ディレクトリに MultiCriteriaDemo.java という名前の新しいファイルを作成します。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class MultiCriteriaDemo {
    public static void main(String[] args) {
        // Create a list of students with some having the same GPA
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.5, 103)); // Same GPA as John
        students.add(new Student("Bob", 3.8, 104));   // Same GPA as Mary
        students.add(new Student("Charlie", 3.2, 105));

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Sort first by GPA, then by name
        Comparator<Student> byGpa = Comparator.comparing(Student::getGpa);
        Comparator<Student> byName = Comparator.comparing(Student::getName);

        // Combine the comparators using thenComparing
        Comparator<Student> byGpaThenName = byGpa.thenComparing(byName);

        // Sort the list
        Collections.sort(students, byGpaThenName);

        // Print the sorted list
        System.out.println("\nStudents sorted by GPA, then by name:");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

このプログラムは以下のことを行います。

  1. 一部の学生が同じ GPA を持つ学生リストを作成します。

  2. GPA 用のコンパレータと名前用のコンパレータを作成します。

  3. thenComparing() メソッドを使用してこれらのコンパレータを結合します。

  4. 学生をまず GPA でソートし、GPA が同じ場合は名前でソートします。

  5. コードをコンパイルして実行します。

cd ~/project
javac Student.java MultiCriteriaDemo.java
java MultiCriteriaDemo

以下のような出力が表示されるはずです。

Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.5, Reg No: 103
Bob, GPA: 3.8, Reg No: 104
Charlie, GPA: 3.2, Reg No: 105

Students sorted by GPA, then by name:
Charlie, GPA: 3.2, Reg No: 105
Alice, GPA: 3.5, Reg No: 103
John, GPA: 3.5, Reg No: 101
Bob, GPA: 3.8, Reg No: 104
Mary, GPA: 3.8, Reg No: 102

同じ GPA を持つ学生(3.5 の Alice と John、3.8 の Bob と Mary)がアルファベット順にソートされていることに注意してください。

逆順でソートする

  1. ~/project ディレクトリに ReverseOrderDemo.java という名前の新しいファイルを作成します。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ReverseOrderDemo {
    public static void main(String[] args) {
        // Create a list of students
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.2, 103));
        students.add(new Student("Bob", 3.9, 104));
        students.add(new Student("Charlie", 3.0, 105));

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Method 1: Using Collections.reverseOrder() with a comparator
        Comparator<Student> byGpa = Comparator.comparing(Student::getGpa);
        Comparator<Student> byGpaReversed = Collections.reverseOrder(byGpa);

        Collections.sort(students, byGpaReversed);

        System.out.println("\nStudents sorted by GPA in descending order (Method 1):");
        for (Student student : students) {
            System.out.println(student);
        }

        // Method 2: Using the reversed() method of Comparator
        Collections.sort(students, Comparator.comparing(Student::getName).reversed());

        System.out.println("\nStudents sorted by name in reverse alphabetical order (Method 2):");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

このプログラムは逆順でソートする 2 つの方法を示しています。

  1. Collections.reverseOrder() を使用してコンパレータを逆にする

  2. コンパレータの reversed() メソッドを使用する

  3. コードをコンパイルして実行します。

cd ~/project
javac Student.java ReverseOrderDemo.java
java ReverseOrderDemo

以下のような出力が表示されるはずです。

Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.2, Reg No: 103
Bob, GPA: 3.9, Reg No: 104
Charlie, GPA: 3.0, Reg No: 105

Students sorted by GPA in descending order (Method 1):
Bob, GPA: 3.9, Reg No: 104
Mary, GPA: 3.8, Reg No: 102
John, GPA: 3.5, Reg No: 101
Alice, GPA: 3.2, Reg No: 103
Charlie, GPA: 3.0, Reg No: 105

Students sorted by name in reverse alphabetical order (Method 2):
Mary, GPA: 3.8, Reg No: 102
John, GPA: 3.5, Reg No: 101
Charlie, GPA: 3.0, Reg No: 105
Bob, GPA: 3.9, Reg No: 104
Alice, GPA: 3.2, Reg No: 103

最初のソートでは学生が GPA の降順で表示され、2 番目のソートでは学生が名前の逆アルファベット順で表示されます。

複雑なソートチェーン

  1. 複数の基準と逆順ソートを組み合わせたもう 1 つの例を作成しましょう。~/project ディレクトリに ComplexSortingDemo.java という名前のファイルを作成します。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComplexSortingDemo {
    public static void main(String[] args) {
        // Create a list of students with varied data
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 3.5, 101));
        students.add(new Student("Mary", 3.8, 102));
        students.add(new Student("Alice", 3.5, 103)); // Same GPA as John
        students.add(new Student("Bob", 3.8, 104));   // Same GPA as Mary
        students.add(new Student("Charlie", 3.2, 105));
        students.add(new Student("David", 3.2, 106)); // Same GPA as Charlie

        // Print the unsorted list
        System.out.println("Unsorted Student List:");
        for (Student student : students) {
            System.out.println(student);
        }

        // Create a complex sorting chain:
        // 1. Sort by GPA in descending order
        // 2. If GPAs are equal, sort by name in ascending order
        // 3. If names are also equal, sort by registration number in descending order
        Comparator<Student> complexComparator = Comparator
            .comparing(Student::getGpa, Comparator.reverseOrder())
            .thenComparing(Student::getName)
            .thenComparing(Student::getRegNo, Comparator.reverseOrder());

        Collections.sort(students, complexComparator);

        System.out.println("\nStudents sorted by complex criteria:");
        System.out.println("(GPA descending, then name ascending, then reg. number descending)");
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

このプログラムは以下のような複雑なソートチェーンを作成します。

  1. まず学生を GPA の降順でソートします。

  2. GPA が同じ場合は、名前の昇順でソートします。

  3. GPA と名前の両方が同じ場合は、登録番号の降順でソートします。

  4. コードをコンパイルして実行します。

cd ~/project
javac Student.java ComplexSortingDemo.java
java ComplexSortingDemo

以下のような出力が表示されるはずです。

Unsorted Student List:
John, GPA: 3.5, Reg No: 101
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.5, Reg No: 103
Bob, GPA: 3.8, Reg No: 104
Charlie, GPA: 3.2, Reg No: 105
David, GPA: 3.2, Reg No: 106

Students sorted by complex criteria:
(GPA descending, then name ascending, then reg. number descending)
Bob, GPA: 3.8, Reg No: 104
Mary, GPA: 3.8, Reg No: 102
Alice, GPA: 3.5, Reg No: 103
John, GPA: 3.5, Reg No: 101
Charlie, GPA: 3.2, Reg No: 105
David, GPA: 3.2, Reg No: 106

この出力では:

  • Bob と Mary はどちらも GPA が 3.8 ですが、アルファベット順で Bob が先に来ます。
  • Alice と John はどちらも GPA が 3.5 ですが、アルファベット順で Alice が先に来ます。
  • Charlie と David はどちらも GPA が 3.2 ですが、アルファベット順で Charlie が先に来ます。

これは、コンパレータをチェーンすることで複雑な多段階のソートロジックを作成できることを示しています。

完全なソートアプリケーションの構築

これまでに Comparable インターフェース、Comparator インターフェース、および様々なソート技術について学びました。それでは、これらすべてを組み合わせて完全なアプリケーションを構築しましょう。

異なる方法で学生をソートできる学生管理システムを作成します。

  1. まず、Student クラスの更新版を作成しましょう。このバージョンでは Comparable を実装し、表示を改善するために改良された toString() メソッドを含めます。~/project ディレクトリに StudentManager.java という名前のファイルを作成します。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

class Student implements Comparable<Student> {
    private String name;
    private double gpa;
    private int regNo;
    private String major;

    public Student(String name, double gpa, int regNo, String major) {
        this.name = name;
        this.gpa = gpa;
        this.regNo = regNo;
        this.major = major;
    }

    @Override
    public int compareTo(Student other) {
        // Default natural ordering by registration number
        return this.regNo - other.regNo;
    }

    // Getters
    public String getName() {
        return name;
    }

    public double getGpa() {
        return gpa;
    }

    public int getRegNo() {
        return regNo;
    }

    public String getMajor() {
        return major;
    }

    @Override
    public String toString() {
        return String.format("%-10s | GPA: %.1f | Reg No: %-5d | Major: %-10s",
                            name, gpa, regNo, major);
    }
}

public class StudentManager {
    private List<Student> students;

    public StudentManager() {
        students = new ArrayList<>();
        // Add some sample students
        students.add(new Student("John", 3.5, 101, "Computer Science"));
        students.add(new Student("Mary", 3.8, 102, "Physics"));
        students.add(new Student("Alice", 3.5, 103, "Mathematics"));
        students.add(new Student("Bob", 3.9, 104, "Computer Science"));
        students.add(new Student("Charlie", 3.2, 105, "Physics"));
        students.add(new Student("David", 3.6, 106, "Mathematics"));
        students.add(new Student("Eve", 3.8, 107, "Biology"));
    }

    public void displayStudents() {
        System.out.println("----------------------------------------------------------");
        System.out.println("Name       | GPA   | Reg No | Major      ");
        System.out.println("----------------------------------------------------------");
        for (Student student : students) {
            System.out.println(student);
        }
        System.out.println("----------------------------------------------------------");
    }

    public void sortByNaturalOrder() {
        Collections.sort(students);
        System.out.println("\nStudents sorted by registration number (natural order):");
        displayStudents();
    }

    public void sortByName() {
        Collections.sort(students, Comparator.comparing(Student::getName));
        System.out.println("\nStudents sorted by name:");
        displayStudents();
    }

    public void sortByGpaDescending() {
        Collections.sort(students, Comparator.comparing(Student::getGpa).reversed());
        System.out.println("\nStudents sorted by GPA (descending):");
        displayStudents();
    }

    public void sortByMajorThenGpa() {
        Collections.sort(students,
            Comparator.comparing(Student::getMajor)
                     .thenComparing(Student::getGpa, Comparator.reverseOrder()));
        System.out.println("\nStudents sorted by major, then by GPA (descending):");
        displayStudents();
    }

    public static void main(String[] args) {
        StudentManager manager = new StudentManager();
        Scanner scanner = new Scanner(System.in);

        while (true) {
            System.out.println("\nStudent Manager");
            System.out.println("1. Display students (unsorted)");
            System.out.println("2. Sort by registration number");
            System.out.println("3. Sort by name");
            System.out.println("4. Sort by GPA (highest first)");
            System.out.println("5. Sort by major, then by GPA (highest first)");
            System.out.println("6. Exit");
            System.out.print("Enter your choice: ");

            int choice = scanner.nextInt();

            switch (choice) {
                case 1:
                    System.out.println("\nUnsorted student list:");
                    manager.displayStudents();
                    break;
                case 2:
                    manager.sortByNaturalOrder();
                    break;
                case 3:
                    manager.sortByName();
                    break;
                case 4:
                    manager.sortByGpaDescending();
                    break;
                case 5:
                    manager.sortByMajorThenGpa();
                    break;
                case 6:
                    System.out.println("Exiting program. Goodbye!");
                    scanner.close();
                    return;
                default:
                    System.out.println("Invalid choice. Please try again.");
            }
        }
    }
}

このアプリケーションは以下のことを行います。

  1. 名前、GPA、登録番号、および専攻を持つ Student クラスを定義します。

  2. 登録番号による自然な順序付けを定義するために Comparable を実装します。

  3. 学生のリストを管理する StudentManager クラスを作成します。

  4. 学生を異なる方法でソートするメソッドを提供します。

  5. ユーザーが異なるソートオプションを選択できる簡単なメニュー駆動型のインターフェースを含めます。

  6. アプリケーションをコンパイルして実行します。

cd ~/project
javac StudentManager.java
java StudentManager
  1. 様々なソートオプションを試してアプリケーションをテストしましょう。以下はサンプルの対話内容です。
Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 1

Unsorted student list:
----------------------------------------------------------
Name       | GPA   | Reg No | Major
----------------------------------------------------------
John       | GPA: 3.5 | Reg No: 101   | Major: Computer Science
Mary       | GPA: 3.8 | Reg No: 102   | Major: Physics
Alice      | GPA: 3.5 | Reg No: 103   | Major: Mathematics
Bob        | GPA: 3.9 | Reg No: 104   | Major: Computer Science
Charlie    | GPA: 3.2 | Reg No: 105   | Major: Physics
David      | GPA: 3.6 | Reg No: 106   | Major: Mathematics
Eve        | GPA: 3.8 | Reg No: 107   | Major: Biology
----------------------------------------------------------

Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 3

Students sorted by name:
----------------------------------------------------------
Name       | GPA   | Reg No | Major
----------------------------------------------------------
Alice      | GPA: 3.5 | Reg No: 103   | Major: Mathematics
Bob        | GPA: 3.9 | Reg No: 104   | Major: Computer Science
Charlie    | GPA: 3.2 | Reg No: 105   | Major: Physics
David      | GPA: 3.6 | Reg No: 106   | Major: Mathematics
Eve        | GPA: 3.8 | Reg No: 107   | Major: Biology
John       | GPA: 3.5 | Reg No: 101   | Major: Computer Science
Mary       | GPA: 3.8 | Reg No: 102   | Major: Physics
----------------------------------------------------------

Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 5

Students sorted by major, then by GPA (descending):
----------------------------------------------------------
Name       | GPA   | Reg No | Major
----------------------------------------------------------
Eve        | GPA: 3.8 | Reg No: 107   | Major: Biology
Bob        | GPA: 3.9 | Reg No: 104   | Major: Computer Science
John       | GPA: 3.5 | Reg No: 101   | Major: Computer Science
David      | GPA: 3.6 | Reg No: 106   | Major: Mathematics
Alice      | GPA: 3.5 | Reg No: 103   | Major: Mathematics
Mary       | GPA: 3.8 | Reg No: 102   | Major: Physics
Charlie    | GPA: 3.2 | Reg No: 105   | Major: Physics
----------------------------------------------------------

Student Manager
1. Display students (unsorted)
2. Sort by registration number
3. Sort by name
4. Sort by GPA (highest first)
5. Sort by major, then by GPA (highest first)
6. Exit
Enter your choice: 6
Exiting program. Goodbye!

異なるソートオプションを試して、学生リストが毎回異なる表示になる様子を確認できます。

この完全なアプリケーションは、Java の Comparable および Comparator インターフェースの強力さと柔軟性を示しています。アプリケーションのさまざまな要件に合わせてオブジェクトを様々な方法でソートすることができます。

まとめ

この実験では、Java で Comparable および Comparator インターフェースを使用してオブジェクトを比較およびソートする方法を学びました。

カバーされた主要な概念は以下の通りです。

  1. Comparable インターフェース

    • クラスの自然な順序付けを定義するために compareTo() メソッドを実装する
    • 自然に順序付けられたオブジェクトで Collections.sort() を使用する
  2. Comparator インターフェース

    • 異なるソート基準のためにカスタムコンパレータを作成する
    • カスタムコンパレータで Collections.sort() を使用する
    • 簡潔なコンパレータ作成のためにラムダ式とメソッド参照を使用する
  3. 高度なソート技術

    • thenComparing() を使用して複数の基準でソートする
    • Collections.reverseOrder() または reversed() を使用して逆順でソートする
    • 複雑なソートチェーンを作成する
  4. 実用的なアプリケーション

    • 様々なソートオプションを持つ完全な学生管理システムを構築する
    • 異なるソート機能を実証するユーザーインターフェースを実装する

これらのソート機能は、多くの Java アプリケーション、特にデータのコレクションを扱うアプリケーションにとって基本的です。学生管理システムの学生をソートする場合、電子商取引アプリケーションの注文をソートする場合、または他のタイプのデータをソートする場合でも、この実験で学んだ技術は効率的で柔軟なソートロジックを実装するのに役立ちます。