JavaRush /Java-Blog /Random-DE /Komparator in Java

Komparator in Java

Veröffentlicht in der Gruppe Random-DE
Hallo! Heute werden wir über den Vergleich von Objekten sprechen. Hmm... Aber wir scheinen darüber schon mehr als einmal gesprochen zu haben? :/ Wir wissen, wie der „ ==“-Operator funktioniert, sowie die equals()und- Methoden hashCode(). Beim Vergleich geht es nicht wirklich darum. Früher meinten wir eher „Objekte auf Gleichheit prüfen“. Komparator in Java - 1Aber der Vergleich von Objekten untereinander kann ganz andere Ziele haben! Das offensichtlichste ist das Sortieren. Ich denke, wenn Sie aufgefordert werden, eine Liste mit Zahlen oder Zeichenfolgen zu sortieren ArrayList<>, können Sie problemlos damit umgehen:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       String name1 = „Mascha“;
       String name2 = „Sascha“;
       String name3 = "Даша";

       List<String> names = new ArrayList<>();
       names.add(name1);
       names.add(name2);
       names.add(name3);

       Collections.sort(names);
       System.out.println(names);
   }
}
Konsolenausgabe:

[Даша, Маша, Саша]
Es ist großartig, wenn Sie sich an die Klasse Collectionsund ihre Methode erinnern sort(). Ich glaube auch nicht, dass es Probleme mit den Zahlen geben wird. Hier ist eine schwierigere Aufgabe für Sie:
public class Car {

   private int manufactureYear;
   private String model;
   private int maxSpeed;

   public Car(int manufactureYear, String model, int maxSpeed) {
       this.manufactureYear = manufactureYear;
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   //...геттеры, сеттеры, toString()

}

import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);
   }
}
Es ist ganz einfach: eine Klasse Carund drei ihrer Objekte. Bitte sortieren Sie die Autos in der Liste! Sie werden sich wahrscheinlich fragen: „Wie sollen sie sortiert werden?“ Nach Namen, nach Baujahr, nach Höchstgeschwindigkeit? Tolle Frage. Wir wissen im Moment nicht, wie man Objekte der Klasse sortiert Car. Und das weiß Java natürlich auch nicht! Collections.sort()Wenn wir versuchen, eine Liste von Objekten an eine Methode zu übergeben Car, erhalten wir eine Fehlermeldung:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(20012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);

       //ошибка компилятора!
       Collections.sort(cars);
   }
}
Und woher weiß die Sprache eigentlich genau, wie die von Ihnen geschriebenen Objekte zu sortieren sind? Es hängt von den Zielen Ihres Programms ab. Wir müssen Java irgendwie beibringen, diese Objekte zu vergleichen. Und vergleichen Sie, wie wir es brauchen. Zu diesem Zweck verfügt Java über eine spezielle Tool-Schnittstelle Comparable. Im Englischen wird dies mit „vergleichbar“ übersetzt. Damit unsere Objekte Carmiteinander verglichen und irgendwie sortiert werden können, muss die Klasse diese Schnittstelle implementieren und ihre einzige Methode implementieren: compareTo():
public class Car implements Comparable<Car> {

   private int manufactureYear;
   private String model;
   private int maxSpeed;

   public Car(int manufactureYear, String model, int maxSpeed) {
       this.manufactureYear = manufactureYear;
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   @Override
   public int compareTo(Car o) {
       return 0;
   }

   //...геттеры, сеттеры, toString()

}
Passt auf:Wir haben die Schnittstelle spezifiziert Comparable<Car>, nicht nur Comparable. Dies ist eine typisierte Schnittstelle, das heißt, sie erfordert die Angabe der spezifischen Klasse, der sie zugeordnet ist. Im Prinzip <Car>kann man es aus der Schnittstelle entfernen, dann vergleicht es aber standardmäßig Objekte Object. Anstelle einer Methode compareTo(Car o)in unserer Klasse haben wir:
@Override
   public int compareTo(Object o) {
       return 0;
   }
Natürlich ist es für uns viel einfacher, damit zu arbeiten Car. Innerhalb der Methode compareTo()implementieren wir die Logik zum Vergleichen von Maschinen. Nehmen wir an, wir müssen sie nach Herstellungsjahr sortieren. Sie haben wahrscheinlich bemerkt, dass die Methode compareTo()den Wert zurückgibt int, nicht boolean. Lassen Sie sich davon nicht überraschen. Tatsache ist, dass der Vergleich zweier Objekte drei mögliche Optionen bietet:
  • а < b
  • a > b
  • a == b.
Es booleanhat nur zwei Werte – wahr und falsch, was für den Vergleich von Objekten unpraktisch ist. Alles ist intviel einfacher. Wenn der Rückgabewert > 0ist, dann a > b. Wenn das Ergebnis compareTo < 0ist, dann а < b. Nun, wenn das Ergebnis ist == 0, dann sind die beiden Objekte gleich: a == b. Unserer Klasse beizubringen, Autos nach Baujahr zu sortieren, ist so einfach wie das Schälen von Birnen:
@Override
public int compareTo(Car o) {
   return this.getManufactureYear() - o.getManufactureYear();
}
Was ist denn hier los? Wir nehmen ein Autoobjekt ( this), das Baujahr dieses Autos und subtrahieren davon das Baujahr eines anderen Autos (desjenigen, mit dem wir das Objekt vergleichen). Wenn das Baujahr des ersten Autos größer ist, gibt die Methode zurück int > 0. Was bedeutet, dass ein Auto this >ein Auto ist о. Wenn hingegen das Baujahr des Zweitwagens ( о) größer ist, dann gibt die Methode eine negative Zahl zurück, und zwar о > this. Wenn sie gleich sind, gibt die Methode zurück 0. Ein solch einfacher Mechanismus reicht bereits aus, um Sammlungen von Objekten zu sortieren Car! Sie müssen nichts weiter tun. Hier bitte:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);

       //тут раньше была ошибка
       Collections.sort(cars);
       System.out.println(cars);
   }
}
Konsolenausgabe:

[Car{manufactureYear=1990, model='Ferrari 360 Spider', maxSpeed=310}, 
Car{manufactureYear=2010, model='Bugatti Veyron', maxSpeed=350}, 
Car{manufactureYear=2012, model='Lamborghini Gallardo', maxSpeed=290}]
Die Autos sind so sortiert, wie sie sein sollten! :) Komparator in Java - 2In welchen Fällen sollte es verwendet werden Comparable? Die implementierte Vergleichsmethode Comparablewird „natürliche Reihenfolge“ genannt. Dies liegt daran, dass Sie in der Methode compareTo()die am häufigsten verwendete Vergleichsmethode beschreiben, die für Objekte dieser Klasse in Ihrem Programm verwendet wird. Natural Ordering ist in Java bereits vorhanden. Java weiß beispielsweise, dass Zeichenfolgen am häufigsten alphabetisch und Zahlen am häufigsten nach aufsteigendem Wert sortiert werden. Wenn Sie die Methode daher für eine Liste von Zahlen oder Zeichenfolgen aufrufen sort(), werden diese sortiert. Wenn in unserem Programm Autos in den meisten Fällen nach Baujahr verglichen und sortiert werden, lohnt es sich, mithilfe der Schnittstelle Comparable<Car>und Methode eine natürliche Sortierung für sie zu definieren compareTo(). Was aber, wenn uns das nicht reicht? Stellen wir uns vor, dass unser Programm nicht so einfach ist. In den meisten Fällen passt die natürliche Sortierung der Autos (wir stellen sie nach Baujahr ein) zu uns. Aber manchmal gibt es unter unseren Kunden auch Fans des schnellen Fahrens. Wenn wir einen Katalog mit Autos zur Auswahl vorbereiten, müssen diese nach Höchstgeschwindigkeit sortiert werden. Komparator in Java - 3Beispielsweise benötigen wir eine solche Sortierung in 15 % der Fälle. CarDies reicht eindeutig nicht aus, um eine natürliche Sortierung nach Geschwindigkeit statt nach Herstellungsjahr festzulegen . Aber wir können 15 % der Kunden nicht ignorieren. Was machen wir? Hier kommt uns eine weitere Schnittstelle zu Hilfe – Comparator. Genau wie , Comparablewird es getippt. Was ist der Unterschied? Comparablemacht unsere Objekte „vergleichbar“ und erstellt für sie die natürlichste Sortierreihenfolge, die in den meisten Fällen verwendet wird. Comparator- Dies ist eine separate „Komparator“-Klasse (die Übersetzung ist etwas umständlich, aber verständlich). Wenn wir eine bestimmte Sortierung implementieren müssen, müssen wir nicht in die Klasse gehen Carund die Logik ändern compareTo(). Stattdessen können wir in unserem Programm eine separate Komparatorklasse erstellen und ihr beibringen, die von uns benötigte Sortierung durchzuführen!
import java.util.Comparator;

public class MaxSpeedCarComparator implements Comparator<Car> {

   @Override
   public int compare(Car o1, Car o2) {
       return o1.getMaxSpeed() - o2.getMaxSpeed();
   }
}
Wie Sie sehen, Comparatorist unsere Lösung ganz einfach. Es gibt nur eine Methode compare()– dies ist eine Schnittstellenmethode Comparator, die implementiert werden muss. Es nimmt zwei Objekte als Eingabe Carund vergleicht ihre maximale Geschwindigkeit auf die übliche Weise (durch Subtraktion). Es compareTo()gibt die Zahl zurück int, das Vergleichsprinzip ist das gleiche. Wie können wir das nutzen? Sehr einfach:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);

       Comparator speedComparator = new MaxSpeedCarComparator();
       Collections.sort(cars, speedComparator);

       System.out.println(cars);
   }
}
Konsolenausgabe:

[Car{manufactureYear=2012, model='Lamborghini Gallardo', maxSpeed=290}, 
Car{manufactureYear=1990, model='Ferrari 360 Spider', maxSpeed=310}, 
Car{manufactureYear=2010, model='Bugatti Veyron', maxSpeed=350}]
Wir erstellen einfach ein Komparatorobjekt und übergeben es Collections.sort()zusammen mit der zu sortierenden Liste an die Methode. Nachdem die Methode einen Komparator als Eingabe erhalten hat, sort()verwendet sie nicht die in der compareTo()Klassenmethode definierte natürliche Sortierung Car. Stattdessen wird der Sortieralgorithmus des an ihn übergebenen Komparators angewendet. Welche Vorteile bringt uns das? Erstens die Kompatibilität mit dem geschriebenen Code. Wir haben eine neue, spezifische Sortiermethode erstellt und dabei die aktuelle beibehalten, die in den meisten Fällen verwendet wird. Wir haben die Klasse überhaupt nicht berührt Car. Er Comparableblieb, wie er war:
public class Car implements Comparable<Car> {

   private int manufactureYear;
   private String model;
   private int maxSpeed;

   public Car(int manufactureYear, String model, int maxSpeed) {
       this.manufactureYear = manufactureYear;
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   @Override
   public int compareTo(Car o) {
       return this.getManufactureYear() - o.getManufactureYear();
   }

   //...геттеры, сеттеры, toString()

}
Zweitens Flexibilität. Wir können so viele Sorten hinzufügen, wie wir möchten. Sortieren Sie Autos beispielsweise nach Farbe, Geschwindigkeit, Gewicht oder wie oft das Auto in Batman-Filmen verwendet wurde. Es reicht aus, einfach ein zusätzliches zu erstellen Comparator. Das ist alles! Heute haben Sie zwei sehr wichtige Mechanismen kennengelernt, die Sie häufig in realen Projekten bei der Arbeit verwenden werden. Aber wie Sie wissen, ist Theorie ohne Praxis nichts. Daher ist es an der Zeit, Ihr Wissen zu festigen und mehrere Probleme zu lösen! :) :)
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION