Comparator und Comparable in Java

Comparator und Comparable in Java

1. Einführung

Vergleiche in Java sind recht einfach - bis sie es nicht sind.

Wenn Sie mit benutzerdefinierten Typen arbeiten oder versuchen, Objekte zu vergleichen, die nicht direkt vergleichbar sind, müssen Sie eine Vergleichsstrategie verwenden. Wir können eine einfach erstellen, aber die SchnittstellenComparator oderComparable verwenden.

2. Einrichten des Beispiels

Nehmen wir ein Beispiel einer Fußballmannschaft, in der wir die Spieler nach ihrer Rangliste sortieren möchten.

Wir beginnen mit der Erstellung einer einfachenPlayer-Klasse:

public class Player {
    private int ranking;
    private String name;
    private int age;

    // constructor, getters, setters
}

Als Nächstes erstellen wir einePlayerSorter-Klasse, um unsere Sammlung zu erstellen, und versuchen, sie mitCollections.sort zu sortieren:

public static void main(String[] args) {
    List footballTeam = new ArrayList<>();
    Player player1 = new Player(59, "John", 20);
    Player player2 = new Player(67, "Roger", 22);
    Player player3 = new Player(45, "Steven", 24);
    footballTeam.add(player1);
    footballTeam.add(player2);
    footballTeam.add(player3);

    System.out.println("Before Sorting : " + footballTeam);
    Collections.sort(footballTeam);
    System.out.println("After Sorting : " + footballTeam);
}

Wie erwartet führt dies hier zu einem Fehler beim Kompilieren:

The method sort(List) in the type Collections
  is not applicable for the arguments (ArrayList)

Lassen Sie uns verstehen, was wir hier falsch gemacht haben.

3. Comparable

Wie der Name schon sagt,Comparable is an interface defining a strategy of comparing an object with other objects of the same type. This is called the class’s “natural ordering”.

Um sortieren zu können, müssen wir unserPlayer-Objekt als vergleichbar definieren, indem wir dieComparable-Schnittstelle implementieren:

public class Player implements Comparable {

    //...
    @Override
    public int compareTo(Player otherPlayer) {
        return (this.getRanking() - otherPlayer.getRanking());
    }
}

Die Sortierreihenfolge wird durch den Rückgabewert voncompareTo() bestimmt Methode.

Die Methode gibt eine Zahl zurück, die angibt, ob das zu vergleichende Objekt kleiner, gleich oder größer als das als Argument übergebene Objekt ist.

Wenn wir jetzt unserePlayerSorter ausführen, können wir sehen, dass unserePlayers nach ihrer Rangfolge sortiert sind:

Before Sorting : [John, Roger, Steven]
After Sorting : [Steven, John, Roger]

Nachdem wir nun ein klares Verständnis der natürlichen Ordnung mitComparable haben, sehen wir unshow we can use other types of ordering, in a more flexible manner an, als eine Schnittstelle direkt zu implementieren.

4. Comparator

The Comparator interface defines a compare(arg1, arg2) method mit zwei Argumenten, die verglichene Objekte darstellen und ähnlich wie die MethodeComparable.compareTo() funktionieren.

4.1. Comparators erstellen

Um einComparator, zu erstellen, müssen wir dieComparator-Schnittstelle implementieren.

In unserem ersten Beispiel erstellen wir einComparator, um dasranking-Attribut vonPlayer zum Sortieren der Spieler zu verwenden:

public class PlayerRankingComparator implements Comparator {

    @Override
    public int compare(Player firstPlayer, Player secondPlayer) {
       return (firstPlayer.getRanking() - secondPlayer.getRanking());
    }
}

In ähnlicher Weise können wir einComparator erstellen, um dasage-Attribut vonPlayer zum Sortieren der Spieler zu verwenden:

public class PlayerAgeComparator implements Comparator {
    @Override
    public int compare(Player firstPlayer, Player secondPlayer) {
       return (firstPlayer.getAge() - secondPlayer.getAge());
    }
}

4.2. Comparators in Aktion

Um das Konzept zu demonstrieren, ändern wir unserePlayerSorter, indem wir ein zweites Argument in dieCollections.sort method einfügen, die tatsächlich die Instanz vonComparator ist, die wir verwenden möchten.

Using this approach, we can override the natural ordering:

PlayerRankingComparator playerComparator = new PlayerRankingComparator();
Collections.sort(footballTeam, playerComparator);

Lassen Sie uns nun unserePlayerRankingSorter toausführen, um das Ergebnis zu sehen:

Before Sorting : [John, Roger, Steven]
After Sorting by ranking : [Steven, John, Roger]

Wenn wir eine andere Sortierreihenfolge wünschen, müssen wir nur dieComparatorändern, die wir verwenden:

PlayerAgeComparator playerComparator = new PlayerAgeComparator();
Collections.sort(footballTeam, playerComparator);

Wenn wir nun unserePlayerAgeSorter ausführen, sehen wir eine andere Sortierreihenfolge nachage:

Before Sorting : [John, Roger, Steven]
After Sorting by age : [Roger, John, Steven]

4.3. Java 8Comparators

Java 8 bietet neue Möglichkeiten zum Definieren vonComparators mithilfe von Lambda-Ausdrücken und der statischen Factory-Methode voncomparing().

Sehen wir uns ein kurzes Beispiel für die Verwendung eines Lambda-Ausdrucks zum Erstellen einesComparatoran:

Comparator byRanking
 = (Player player1, Player player2) -> player1.getRanking() - player2.getRanking();

Die MethodeComparator.comparingverwendet eine Methode zur Berechnung der Eigenschaft, die zum Vergleichen von Elementen verwendet wird, und gibt eine übereinstimmende Instanz vonComparatorzurück:

Comparator byRanking = Comparator
  .comparing(Player::getRanking);
Comparator byAge = Comparator
  .comparing(Player::getAge);

Sie können die Java 8-Funktionalität in unseremJava 8 Comparator.comparing-Handbuch ausführlich untersuchen.

5. Comparator VsComparable

The Comparable interface is a good choice when used for defining the default ordering oder mit anderen Worten, wenn dies die Hauptmethode zum Vergleichen von Objekten ist.

Dann müssen wir uns fragen, warum wirComparator verwenden, wenn wir bereitsComparable haben.

Dafür gibt es mehrere Gründe:

  • Manchmal können wir den Quellcode der Klasse, deren Objekte wir sortieren möchten, nicht ändern, wodurch die Verwendung vonComparableunmöglich wird

  • Durch die Verwendung vonComparators können wir vermeiden, unseren Domänenklassen zusätzlichen Code hinzuzufügen

  • Wir können mehrere verschiedene Vergleichsstrategien definieren, die bei Verwendung vonComparable nicht möglich sind

6. Fazit

In diesem Tutorial haben wir die SchnittstellenComparable undComparator untersucht und die Unterschiede zwischen ihnen diskutiert.

Weitere Informationen zum Sortieren finden Sie in unseren anderen Artikeln wieJava 8 Comparator,Java 8 Comparison with Lambdas.

Und wie üblich kann der Quellcodeover on Github gefunden werden.