Vergleichbar und Comparator in Java Beispiel

Comparable und Comparator in Java sind sehr nützlich, um eine Sammlung von Objekten zu sortieren. Java bietet einige eingebaute Methoden zum Sortieren von Arrays oder Listen von primitiven Datentypen oder Wrapper-Klassen. Hier lernen wir zunächst, wie wir ein Array/eine Liste von primitiven Datentypen und Wrapper-Klassen sortieren können, und anschließend verwenden wir die Schnittstellen java.lang.Comparable und java.util.Comparator, um ein Array/eine Liste von benutzerdefinierten Klassen zu sortieren. Schauen wir uns an, wie wir ein Array/ eine Liste von primitiven Datentypen oder Objekten mit einem einfachen Programm sortieren können.

package com.journaldev.sort;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class JavaObjectSorting {

    /**
     * This class shows how to sort primitive arrays, 
     * Wrapper classes Object Arrays
     * @param args
     */
    public static void main(String[] args) {
         // Sortiere primitives Array wie int-Array
        int[] intArr = {5,9,1,10};
        Arrays.sort(intArr);
        System.out.println(Arrays.toString(intArr));
        
         // Sortiere String-Array
        String[] strArr = {"A", "C", "B", "Z", "E"};
        Arrays.sort(strArr);
        System.out.println(Arrays.toString(strArr));
        
         // Sortiere Liste von Objekten von Wrapper-Klassen
        List strList = new ArrayList();
        strList.add("A");
        strList.add("C");
        strList.add("B");
        strList.add("Z");
        strList.add("E");
        Collections.sort(strList);
        for(String str: strList) System.out.print(" "+str);
    }
}

Die Ausgabe des obigen Programms ist:

[1, 5, 9, 10]
[A, B, C, E, Z]
 A B C E Z

Jetzt versuchen wir, ein Array von Objekten zu sortieren.

package com.journaldev.sort;

public class Employee {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
     // Diese Methode wird überschrieben, um Informationen über den Mitarbeiter in benutzerfreundlicher Form auszugeben
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

}

Hier ist der Code, den ich verwendet habe, um das Array von Mitarbeiter-Objekten zu sortieren.

 // Sortiere Objekt-Array
Employee[] empArr = new Employee[4];
empArr[0] = new Employee(10, "Mikey", 25, 10000);
empArr[1] = new Employee(20, "Arun", 29, 20000);
empArr[2] = new Employee(5, "Lisa", 35, 5000);
empArr[3] = new Employee(1, "Pankaj", 32, 50000);

 // Sortiere Mitarbeiter-Array mit Implementierung der Comparable-Schnittstelle
Arrays.sort(empArr);
System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));

Als ich versuchte, dies auszuführen, trat folgende Laufzeit-Ausnahme auf.

Exception in thread "main" java.lang.ClassCastException: com.journaldev.sort.Employee cannot be cast to java.lang.Comparable
	at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290)
	at java.util.ComparableTimSort.sort(ComparableTimSort.java:157)
	at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
	at java.util.Arrays.sort(Arrays.java:472)
	at com.journaldev.sort.JavaSorting.main(JavaSorting.java:41)

Comparable und Comparator

Java bietet das Comparable-Interface, das von jeder benutzerdefinierten Klasse implementiert werden sollte, wenn wir die Sortiermethoden von Arrays oder Collections verwenden möchten. Das Comparable-Interface verfügt über die Methode compareTo(T obj), die von den Sortiermethoden verwendet wird. Sie können jede Wrapper-, String- oder Datei-Klasse überprüfen, um dies zu bestätigen. Wir sollten diese Methode so überschreiben, dass sie einen negativen ganzzahligen Wert, null oder einen positiven ganzzahligen Wert zurückgibt, wenn das „this“-Objekt weniger als, gleich oder größer als das als Argument übergebene Objekt ist. Nach der Implementierung des Comparable-Interfaces in der Mitarbeiterklasse sieht die resultierende Mitarbeiterklasse folgendermaßen aus.

package com.journaldev.sort;

import java.util.Comparator;

public class Employee implements Comparable {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee emp) {
        //Lassen Sie uns die Mitarbeiter basierend auf einer ID in aufsteigender Reihenfolge sortieren
        //gibt einen negativen ganzzahligen Wert, null oder einen positiven ganzzahligen Wert zurück, wenn diese Mitarbeiter-ID
        //kleiner, gleich oder größer als das angegebene Objekt ist.
        return (this.id - emp.id);
    }

    @Override
    //Dies ist erforderlich, um die benutzerfreundlichen Informationen über den Mitarbeiter auszudrucken
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

}

Wenn wir nun den obigen Ausschnitt für die Arrays-Sortierung von Mitarbeitern ausführen und ihn ausdrucken, lautet die Ausgabe.

Default Sorting of Employees list:
[[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]]

Wie Sie sehen können, ist das Employees-Array nach ID in aufsteigender Reihenfolge sortiert. Aber in den meisten realen Szenarien möchten wir eine Sortierung basierend auf verschiedenen Parametern. Zum Beispiel möchte ich als CEO die Mitarbeiter nach Gehalt sortieren, ein Personalverantwortlicher möchte sie nach Alter sortieren. Dies ist die Situation, in der wir das Java Comparator-Interface verwenden müssen, weil die Implementierung der Comparable.compareTo(Object o)-Methode eine Standard-Sortierung bietet und wir sie nicht dynamisch ändern können. Während wir mit Comparator mehrere Methoden definieren können, um verschiedene Sortiermethoden zu definieren, und dann die Sortiermethode basierend auf unseren Anforderungen auswählen können.

Java Comparator

Die Comparator-Schnittstelle compare(Object o1, Object o2) muss implementiert werden, die zwei Objektargumente akzeptiert. Sie sollte so implementiert sein, dass sie eine negative Ganzzahl zurückgibt, wenn das erste Argument kleiner ist als das zweite, und null, wenn sie gleich sind, sowie eine positive Ganzzahl, wenn das erste Argument größer ist als das zweite. Comparable und Comparator Schnittstellen verwenden Generics für die Typüberprüfung zur Compile-Zeit, erfahren Sie mehr über Java Generics. So können wir verschiedene Comparator-Implementierungen in der Employee-Klasse erstellen.

/**
     * Comparator to sort employees list or array in order of Salary
     */
    public static Comparator<Employee> SalaryComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return (int) (e1.getSalary() - e2.getSalary());
        }
    };

    /**
     * Comparator to sort employees list or array in order of Age
     */
    public static Comparator<Employee> AgeComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getAge() - e2.getAge();
        }
    };

    /**
     * Comparator to sort employees list or array in order of Name
     */
    public static Comparator<Employee> NameComparator = new Comparator<Employee>() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };

Alle oben aufgeführten Implementierungen des Comparator-Interface sind anonyme Klassen. Wir können diese Komparatoren verwenden, um ein Argument an die Sortierfunktion der Klassen Arrays und Collections zu übergeben.

//sortiere das Mitarbeiter-Array mit dem Vergleicher nach Gehalt
Arrays.sort(empArr, Employee.SalaryComparator);
System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));

//sortiere das Mitarbeiter-Array mit dem Vergleicher nach Alter
Arrays.sort(empArr, Employee.AgeComparator);
System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));

//sortiere das Mitarbeiter-Array mit dem Vergleicher nach Namen
Arrays.sort(empArr, Employee.NameComparator);
System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));

Hier ist die Ausgabe des obigen Code-Ausschnitts:

Employees list sorted by Salary:
[[id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by Age:
[[id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000]]
Employees list sorted by Name:
[[id=20, name=Arun, age=29, salary=20000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000]]

Wir wissen jetzt also, dass wir, wenn wir ein Java-Objekt-Array oder eine Liste sortieren wollen, das Java Comparable Interface implementieren müssen, um eine Standardsortierung bereitzustellen, und wir sollten das Java Comparator Interface implementieren, um verschiedene Sortiermethoden bereitzustellen. Wir können auch eine separate Klasse erstellen, die das Comparator-Interface implementiert und dann verwenden. Hier sind die abschließenden Klassen, die wir zur Erklärung von Comparable und Comparator in Java haben.

package com.journaldev.sort;

import java.util.Comparator;

public class Employee implements Comparable {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee emp) {
        //sortieren wir den Mitarbeiter basierend auf einer ID in aufsteigender Reihenfolge
        //gibt eine negative Ganzzahl, Null oder eine positive Ganzzahl zurück, wenn diese Mitarbeiter-ID
        //kleiner als, gleich oder größer als das angegebene Objekt ist.
        return (this.id - emp.id);
    }

    @Override
    //dies ist erforderlich, um benutzerfreundliche Informationen über den Mitarbeiter auszudrucken
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

    /**
     * Comparator to sort employees list or array in order of Salary
     */
    public static Comparator SalaryComparator = new Comparator() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return (int) (e1.getSalary() - e2.getSalary());
        }
    };

    /**
     * Comparator to sort employees list or array in order of Age
     */
    public static Comparator AgeComparator = new Comparator() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getAge() - e2.getAge();
        }
    };

    /**
     * Comparator to sort employees list or array in order of Name
     */
    public static Comparator NameComparator = new Comparator() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };
}

Hier ist die separate Klassenimplementierung des Comparator-Interface, die zwei Mitarbeiterobjekte zuerst nach ihrer ID und wenn sie gleich sind, dann nach dem Namen vergleicht.

package com.journaldev.sort;

import java.util.Comparator;

public class EmployeeComparatorByIdAndName implements Comparator<Employee> {

    @Override
    public int compare(Employee o1, Employee o2) {
        int flag = o1.getId() - o2.getId();
        if(flag==0) flag = o1.getName().compareTo(o2.getName());
        return flag;
    }

}

Hier ist die Testklasse, in der wir verschiedene Methoden verwenden, um Objekte in Java mit Comparable und Comparator zu sortieren.

package com.journaldev.sort;

import java.util.Arrays;

public class JavaObjectSorting {

    /**
     * This class shows how to sort custom objects array/list
     * implementing Comparable and Comparator interfaces
     * @param args
     */
    public static void main(String[] args) {

        //Sortierung von benutzerdefiniertem Objekt-Array
        Employee[] empArr = new Employee[4];
        empArr[0] = new Employee(10, "Mikey", 25, 10000);
        empArr[1] = new Employee(20, "Arun", 29, 20000);
        empArr[2] = new Employee(5, "Lisa", 35, 5000);
        empArr[3] = new Employee(1, "Pankaj", 32, 50000);
        
        //Sortierung von Mitarbeiter-Array mithilfe der Implementierung des Comparable-Interface
        Arrays.sort(empArr);
        System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));
        
        //Sortieren Sie das Mitarbeiter-Array nach Gehalt mithilfe des Comparator
        Arrays.sort(empArr, Employee.SalaryComparator);
        System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));
        
        //Sortieren Sie das Mitarbeiter-Array nach Alter mithilfe des Comparator
        Arrays.sort(empArr, Employee.AgeComparator);
        System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));
        
        //Sortieren Sie das Mitarbeiter-Array nach Namen mithilfe des Comparator
        Arrays.sort(empArr, Employee.NameComparator);
        System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));
        
        //Mitarbeiterliste nach ID und dann Namen sortiert unter Verwendung der Comparator-Klasse
        empArr[0] = new Employee(1, "Mikey", 25, 10000);
        Arrays.sort(empArr, new EmployeeComparatorByIdAndName());
        System.out.println("Employees list sorted by ID and Name:\n"+Arrays.toString(empArr));
    }

}

Hier ist die Ausgabe des obigen Programms:

Default Sorting of Employees list:
[[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]]
Employees list sorted by Salary:
[[id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by Age:
[[id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000]]
Employees list sorted by Name:
[[id=20, name=Arun, age=29, salary=20000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by ID and Name:
[[id=1, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000]]

Die java.lang.Comparable und java.util.Comparator sind leistungsstarke Schnittstellen, die verwendet werden können, um Objekte in Java zu sortieren.

Vergleichbar vs. Vergleichbar

  1. Das Comparable-Interface kann verwendet werden, um eine einzige Sortierreihenfolge bereitzustellen, während das Comparator-Interface verwendet wird, um verschiedene Sortierreihenfolgen bereitzustellen.
  2. Um Comparable zu verwenden, muss die Klasse es implementieren, während wir für Comparator keine Änderung an der Klasse vornehmen müssen.
  3. Das Comparable-Interface befindet sich im Paket java.lang, während das Comparator-Interface im Paket java.util vorhanden ist.
  4. Es sind keine Codeänderungen auf der Clientseite erforderlich, um Comparable zu verwenden. Die Methoden Arrays.sort() oder Collection.sort() verwenden automatisch die Methode compareTo() der Klasse. Für Comparator muss der Client die Comparator-Klasse im compare()-Methode bereitstellen.

Weißt du, dass die Collections.sort() Methode, die einen Comparator-Argument folgt, das Strategie-Muster verwendet?

Sie können den vollständigen Code und weitere Beispiele in Core Java in unserem GitHub-Repository überprüfen.

Source:
https://www.digitalocean.com/community/tutorials/comparable-and-comparator-in-java-example