Spezielle frage zum Comparator

niklas._.kpl

Mitglied
Hallo, ich habe eine etwas speziellere frage zu "implements Comparator". Es funktioniert in meinem Programm zwar alles wie es soll, aber ich würde gerne die Funktion dahinter verstehen wie es funktioniert. Ich habe eine eigene Klasse namens Person erstellt, diese hat 2 Eigenschaften (String name und int Alter) nun habe ich noch 2 weitere Klassen für den Comparator erstellt, der eine Sortiert nach den Namen und der andere Sortiert nach dem Alter:
Java:
class SortiereAngestelltenNamen implements Comparator<Angestellter> {

    @Override
    public int compare(Angestellter o1, Angestellter o2) {

        return o1.getName().compareTo(o2.getName());
    }

}

class SortiereAngestelltenAlter implements Comparator<Angestellter> {

    public int compare(Angestellter o1, Angestellter o2) {

        if (o1.getAlter() > o2.getAlter()) {
            return 1;
        } else if (o1.getAlter() < o2.getAlter()) {
            return -1;
        } else {
            return 0;
        }
    }

}

Wenn ich jetzt eine ArrayList (gefüllt mit Personen Objekten) Sortieren möchte, mache ich das ja wie Folgt:
Code:
        Collections.sort(angestelltenListe, new SortiereAngestelltenAlter());

Um zu herauszufinden, wie die Funktionsweise ist, habe ich einfach mal in meiner Comparator Klasse das implements weggelassen, dann entsteht sofort ein Fehler aber warum? Eigentlich benötigen wir doch das Interface nur auf die eine Unimplementierte Methode zuzugreifen, danach benötigen wir doch das Interface eigentlich nicht mehr oder verstehe ich da etwas Falsch? Die Funktion sort( ) greift doch auf die von mir erstellte Klasse zu. Warum benötigt es dann noch das Interface, vom dem wir die Funktion aufrufen (Beim erstellen). Ich hoffe, meine Frage ist nicht zu verwirrend, will die Funktionsweise dahinter nur richtig verstehen.
 
Um zu herauszufinden, wie die Funktionsweise ist, habe ich einfach mal in meiner Comparator Klasse das implements weggelassen, dann entsteht sofort ein Fehler aber warum?
Der sort Aufruf will einen Comparator als Parameter. Wenn Du da etwas übergibst, das kein Comparator ist, dann gibt es einen Fehler.

Eigentlich benötigen wir doch das Interface nur auf die eine Unimplementierte Methode zuzugreifen, danach benötigen wir doch das Interface eigentlich nicht mehr oder verstehe ich da etwas Falsch? Die Funktion sort( ) greift doch auf die von mir erstellte Klasse zu. Warum benötigt es dann noch das Interface, vom dem wir die Funktion aufrufen (Beim erstellen). Ich hoffe, meine Frage ist nicht zu verwirrend, will die Funktionsweise dahinter nur richtig verstehen.
Das Interface benötigen wir auf jeden Fall, denn das ist ja der geforderte Parameter.
Worauf Du evtl. hinaus willst, ist der Fakt, dass es sich hier um ein funktionales Interface handelt. Damit kann dieses auch per Lambda Expression oder Methodenreferenz erfüllt werden.

Also wenn Du die Klassen etwas umänderst und die Methode statisch machst (gibt ja kein State oder so), dann würde es kein implements mehr geben und das Alles sähe es so aus (Mit etwas umbenannten Methoden):
Java:
class AngestelltenSortierungen {
    public static int compareByName(Angestellter o1, Angestellter o2) {
        return o1.getName().compareTo(o2.getName());
    }
}

Nutzung mit Lambda Expression: Collections.sort(angestelltenListe, (a1, a2) -> AngestelltenSortierungen.compareByName(a1,a2));
Nutzung mit Methodenreferenz: Collections.sort(angestelltenListe, AngestelltenSortierungen::compareByName);

Die Implementation eines funktionalen Interfaces ist also wirklich eher unüblich. Statt dessen nutzt man eine Methode mit der notwendigen Signatur (und beliebigem Namen) um diese dann zu nutzen.

So kannst Du dann z.B. eine Klasse mit vielen Sortierungen bereit stellen.

Und wenn wir die Implementierungen ansehen: Das ist auch so eher unüblich. Comparator hat comparing Methoden. Diese compareByName Implementation wäre also etwas wie Comparator.comparing(Angestellter::getName)

Damit wäre der resultierende Aufruf schlicht etwas wie:
Collections.sort(list, Comparator.comparing(Angestellter::getName));
oder
Collections.sort(list, Comparator.comparingInt(Angestellter::getAlter));
 
Der sort Aufruf will einen Comparator als Parameter. Wenn Du da etwas übergibst, das kein Comparator ist, dann gibt es einen Fehler.


Das Interface benötigen wir auf jeden Fall, denn das ist ja der geforderte Parameter.
Worauf Du evtl. hinaus willst, ist der Fakt, dass es sich hier um ein funktionales Interface handelt. Damit kann dieses auch per Lambda Expression oder Methodenreferenz erfüllt werden.

Also wenn Du die Klassen etwas umänderst und die Methode statisch machst (gibt ja kein State oder so), dann würde es kein implements mehr geben und das Alles sähe es so aus (Mit etwas umbenannten Methoden):
Java:
class AngestelltenSortierungen {
    public static int compareByName(Angestellter o1, Angestellter o2) {
        return o1.getName().compareTo(o2.getName());
    }
}

Nutzung mit Lambda Expression: Collections.sort(angestelltenListe, (a1, a2) -> AngestelltenSortierungen.compareByName(a1,a2));
Nutzung mit Methodenreferenz: Collections.sort(angestelltenListe, AngestelltenSortierungen::compareByName);

Die Implementation eines funktionalen Interfaces ist also wirklich eher unüblich. Statt dessen nutzt man eine Methode mit der notwendigen Signatur (und beliebigem Namen) um diese dann zu nutzen.

So kannst Du dann z.B. eine Klasse mit vielen Sortierungen bereit stellen.

Und wenn wir die Implementierungen ansehen: Das ist auch so eher unüblich. Comparator hat comparing Methoden. Diese compareByName Implementation wäre also etwas wie Comparator.comparing(Angestellter::getName)

Damit wäre der resultierende Aufruf schlicht etwas wie:
Collections.sort(list, Comparator.comparing(Angestellter::getName));
oder
Collections.sort(list, Comparator.comparingInt(Angestellter::getAlter));
Danke für die Ausführliche Antwort, bin gerade erst am Anfang und habe noch keine Ahnung wie Lambda funktioniert das kommt in meinem Kurs erst etwas Später. Habe immer gedacht implements Interface heißt das die Klasse nur von dem Interface erbt und dann war es das aber das ist sohl Falsch gedacht?
 
Habe immer gedacht implements Interface heißt das die Klasse nur von dem Interface erbt und dann war es das aber das ist sohl Falsch gedacht?
Prinzipiell ist das so durchaus richtig. So Sprachen sind da sehr formell. Du kannst Dir das so vorstellen als wäre der Compiler einer Beamter, der etwas prüft. Dann reicht es nicht, dass ein Gerät z.B. eine Norm erfüllt. Es muss auch drauf stehen. Es reicht also nicht, dass die Klasse die Methoden hat, die das Interface vorgibt, sondern es muss auch klar dokumentiert sein (durch das implements ....).
 
Danke erstmal für die vielen schnellen Antworten. Habe verstanden, weshalb es so sein muss, ich denke, wenn ich in meinem Java Kurs weiter zu Lambdas und funktionalen Interfaces komme, wird sich der Kreis noch mehr schließen. Euch einen schönen Tag.
 

Zurück
Oben