Hallo,
ich habe versucht mich in das Thema einzulesen (Literatur & Internet) jedoch komme ich kein Stück voran:
Wie kann man die comparable Methode implementieren, sodass diese zwei Objekte Miteinander vergleicht?
Einmal hat das absolut nichts mit der Frage zu tun, in der es um Comparator geht, und andererseits ist der Stil echt schlecht.
Das if-else würde man schreiben als return o.equals(c), und damit wäre die Methode im wesentlichen, eine vorhandene Methode in eine statische auszulagern und unsinnig zu benennen, die hat genau gar keinen Vorteil gegenüber o.equals(c), außer zusätzlichen Imports und schlechterer Lesbarkeit.
Die zu implementierende Methode hätte die Signatur compare(Person p1, Person p2) und müsste -1 zurückgeben, wenn p1 jünger als p2 ist, 0 wenn sie gleich alt sind und 1, wenn p1 älter als p2 ist?
Die zu implementierende Methode hätte die Signatur compare(Person p1, Person p2) und müsste -1 zurückgeben, wenn p1 jünger als p2 ist, 0 wenn sie gleich alt sind und 1, wenn p1 älter als p2 ist?
Klar, nach der ersten Bedingung lieferst du ja einen Rückgabewert. Der Rest wird niemals ausgeführt. Der "Else" Fall kommt zum Schluss. Einen der 3 Fälle musst du nicht prüfen. Die Zahl ist entweder größer oder sie ist gleich ODER (else-Fall) sie ist kleiner (Reihenfolge wurscht). Wenn sie also weder größer noch kleiner ist, dann musst du nicht mehr prüfen, ob sie kleiner ist. Anstatt der 3. Bedingung musst du einfach den Rückgabewert derselben liefern.
Hier 3 Möglichkeiten zum anständigen Coden (alle zulässig, stehen auch im originalen Java-Quellcode so drin)
Die 4. Methode zeigt dir, wie du weitermachst, wenn du mehr als nur das Alter vergleichen willst.
Java:
/**
* relativ "saubere" Variante, allerdings werden mehrere 'return' verwendet, das sollten Anfänger nicht machen. V2 ist für Anfänger besser
*/publicintcompareV1(Person p1,Person p2){if(p1.alter > p2.alter){return-1;}elseif(p1.alter < p2.alter){return1;}else{//Auf Gleichheit musst du nicht mehr prüfenreturn0;}}/**
* "sauberste" Variante, so wie man es lernen sollte.
*/publicintcompareV2(Person p1,Person p2){//Beachte: returnvalue wird hier am Anfang nicht initialisiert, der Compiler warnt dich also, wenn du es auswerten willst, so lange noch kein Wert gesetzt ist.int returnvalue;if(p1.alter > p2.alter){
returnvalue =-1;}elseif(p1.alter < p2.alter){
returnvalue =1;}else{//Auf Gleichheit musst du nicht mehr prüfen
returnvalue =0;}//Erst an diesem Punkt hat returnvalue garantiert einen Wert und darf weiterverwendet werden.return returnvalue;}/**
* Diese Variante hat weniger Else-Bereiche, ist als etwas resourcenschonender, liefert aber auch immer direkt das Ergebnis. Für Anfänger nicht geeignet.
*/publicintcompareV3(Person p1,Person p2){if(p1.alter > p2.alter){return-1;}if(p1.alter < p2.alter){return1;}//Auf Gleichheit musst du nicht mehr prüfenreturn0;}/**
* Für mehrere Vergleiche
*
* @param p1
* @param p2
* @return
*/publicintcompareV4(Person p1,Person p2){//Kürzen wir das Ganze etwas ab, für Integer gibt es bereits eine Compare-Funktion, schau dir deren Quellcode mal anint returnvalue =Integer.compare(p1.alter, p2.alter);//Alter verschieden, Ergebnis liefernif(returnvalue !=0){return returnvalue;}//Alter gleich, es muss weiter verglichen werden
returnvalue =compareTwoStrings(p1.name, p2.name);//Keine weiteren Vergleichsoptionen vorhanden, also einfach den Wert liefern. Ansonsten hier returnValue wieder auf 0 prüfen und den nächsten Parameter prüfenreturn returnvalue;}/**
* String-Vergleich ohne Nullpointer-Exception
* @param s1 String1
* @param s2 String2
* @return Beide Werte null: 0, s1 == null: 1, s2 == null: -1
*/privateintcompareTwoStrings(String s1,String s2){if(s1 ==null){//Wenn beide Namen auf null gesetzt sind, dann als "gleich" betrachten, also Ergebnis 0//Nur p1.name == null ? 1return s2 ==null?0:1;}if(s2 ==null){//nur p2.name == null? -1return-1;}//ansonsten echt vergleichen lassenreturn s1.compareTo(s2);}
Man kann natürlich nach Belieben kombinieren, das sind nur 3 Beispiele. Aber fange an, deinen Code wie in V2 zu schreiben, das ist die ordentlichste Methode.
ps: Schreib Wrapper für deine Instanzvariablen (public String getName(){...} und public void setName(String value){...}). Direkter Zugriff == nixGut;
Also nicht "p1.name" verwenden, sondern "p1.getName()", "name" selbst gehört auf private gesetzt.
Warum? Compiler warnt dich auch hier, dass ein Pfad nichts returned V2 ist äquivalent zu V1
Bei V4 gibt es schon was wie Comparator::nullsFirst oder Comparator::nullsLast. Aber es sollte meiner Meinung nach da richtig krachen, denn welche Person hat denn keinen Namen?
Warum? Compiler warnt dich auch hier, dass ein Pfad nichts returned V2 ist äquivalent zu V1
Bei V4 gibt es schon was wie Comparator::nullsFirst oder Comparator::nullsLast. Aber es sollte meiner Meinung nach da richtig krachen, denn welche Person hat denn keinen Namen?
Warum ... zum besseren Verständnis. Returns mitten in einer Methode sind mitunter eine recht unübersichtliche Art zu Arbeiten. Ein Anfänger sollte sich auf ein Return pro Methode beschränken und den Workflow verstehen, bevor er so was macht. Der Thread-Ersteller muss sich erst noch mit if-then-else beschäftigen und damit, was bei einem return passiert, sonst würde er diese Fragen nicht stellen (siehe "unreachable code").
Zu V4 ... cool, wusste ich gar nicht, danke.
Wenn wir davon ausgehen, dass jedes Personenobjekt einen gültigen Namen haben MUSS, dann sollte setName(null) eine entsprechende Exception werfen und nicht erst der Comparator.
Wenn wir davon ausgehen, dass jedes Personenobjekt einen gültigen Namen haben MUSS, dann sollte setName(null) eine entsprechende Exception werfen und nicht erst der Comparator.
Warum ... zum besseren Verständnis. Returns mitten in einer Methode sind mitunter eine recht unübersichtliche Art zu Arbeiten. Ein Anfänger sollte sich auf ein Return pro Methode beschränken und den Workflow verstehen, bevor er so was macht. Der Thread-Ersteller muss sich erst noch mit if-then-else beschäftigen und damit, was bei einem return passiert, sonst würde er diese Fragen nicht stellen (siehe "unreachable code").
Das seh ich aber genau umgekehrt. Frühes Verlassen einer Methode hat den Vorteil zu wissen, dass weiter nachfolgender Code nicht mehr ausgeführt wird und muss nicht sicherstellen (meist verbunden mit weiteren/redundanten if-Abfragen) das dieser nicht ausgeführt wird.
Das seh ich aber genau umgekehrt. Frühes Verlassen einer Methode hat den Vorteil zu wissen, dass weiter nachfolgender Code nicht mehr ausgeführt wird und muss nicht sicherstellen (meist verbunden mit weiteren/redundanten if-Abfragen) das dieser nicht ausgeführt wird.
Ich stimmer dir zu, dass das ein Vorteil ist (ich arbeite vor allem bei Vergleichsmthoden ja auch so), aber zum Lernen ist es besser, wenn man übt, die komplette Logik im Auge zu behalten. Gerade bei längeren Methoden sucht man sich sonst einen ab, alle returns zu finden.
Im Idealfall schreibt man sich gerade als Anfänger die Logik einer Methode erst mal als Struktogramm (oder in einem ähnlichen Hilfsmittel) auf, bevor man zu coden beginnt.
Ist halt Ansichtssache
Lustig, ihr arbeitet euch hier an einem Thema ab das bestimmt schon lange behoben ist. Ich tippe mal der TE hat längst auf Subtraktion umgestellt, alles funktioniert und er traut sich jetzt nicht das hier zu posten