compareTo nach mehreren Kriterien

ocsme

Top Contributor
Guten Tag,

hier sind zwei Klassen:

Java:
import java.util.*;

public class Gruppe implements Contact, Comparable<Contact> {
    String name;
    Set<Contact> eintraege;
    
    Gruppe() {
        
    }
    
    Gruppe(String n) {
        eintraege = new TreeSet<>();
        name=n;
    }
    
    public boolean add(Contact c) {
        if(c!=this)
            return eintraege.add(c) ;
        return false;
    }
    
    public String toString() {
        String ret = name;
        Iterator<Contact> it = entries.iterator();
        while(it.hasNext())
            ret+="\n"+it.next().toString();
        return ret;
    }

    @Override
    public int compareTo(Contact c) {
        if(c instanceof Gruppe) {
            return name.compareTo(((Gruppe) c).name);
        }
        return 1;
    }

}

Java:
import java.util.*;
public class Person implements Contact, Comparable<Contact>{
    
    String title;
    String firstName;
    String lastName;
    
    Person(String f, String l) {
        this(null,f,l);
    }
    
    Person(String t, String f, String l) {
        title=t;
        firstName=f;
        lastName=l;
    }
    
    public String toString() {
        return (title!=null) ?
                title+" "+((firstName!=null)?firstName+" "+((lastName!=null)?lastName:"") :"")
                : firstName!=null?firstName+" "+lastName:"";
    }

    @Override
    public int compareTo(Contact o) {
        if(o instanceof Person) {
            return lastName.compareTo(((Person) o).lastName);
        }
        else
            return -1;
    }
    
}

Das Interface
Java:
public interface Contact {
     // nothing here marker interface
}


Nun weiß ich nicht ob es mit einem Set überhaupt geht wenn nicht muss ich alles in eine Liste machen.
Was ich tun möchte ist, bei Person nach dem Nachnamen vergleichen sollten diese gleich sein soll nach dem Vornamen verglichen werden dann nach dem Vorname und danach nach dem Titel.

Somit soll z. B.:
Person p1 = new Person("Max", "Mustermann");
Person p2 = new Person("Dr", "Max", "Mustermann");

p1 und p2 sollen eingeordnet werden können.
Leider stehe ich hierbei irgendwie super auf dem Schlauch. Ich hab schon so etwas ausprobiert doch das ist ja Käse :p
Java:
    @Override
    public int compareTo(Contact o) {
        if(o instanceof Person) {
            if(lastName.compareTo(((Person) o).lastName) != 0)
                return lastName.compareTo(((Person) o).lastName);
            else if(firstName.compareTo(((Person)o).firstName) != 0)
                    return firstName.compareTo((((Person)o).firstName));
                    else
                        return title.length()-((Person) o).title.length();
        }
        return -1;
    }

Kann mir da jemand eine Idee geben?
 

mrBrown

Super-Moderator
Mitarbeiter
Dafür kannst du zB Comparator#thenComparing nutzen, Beispiele sollten sich dafür im JavaDoc finden lassen :)
 

ocsme

Top Contributor
meinst du das hier?
Java:
default Comparator<T> thenComparing(Comparator<? super T> other)

Ich will ja eigentlich nur Fragen wenn es einen Titel gibt vergleiche so gibt es keinen vergleiche so :p

LG
 

mrBrown

Super-Moderator
Mitarbeiter
meinst du das hier?
Java:
default Comparator<T> thenComparing(Comparator<? super T> other)

Ich will ja eigentlich nur Fragen wenn es einen Titel gibt vergleiche so gibt es keinen vergleiche so :p
Genau dafür ist diese Methode da ;)

Du kannst das natürlich auch per Hand schreiben, wenn du das gerne möchtest, musst halt dann ==0 und !=0 entsprechend behandeln.
 

ocsme

Top Contributor
Du kannst das natürlich auch per Hand schreiben, wenn du das gerne möchtest, musst halt dann ==0 und !=0 entsprechend behandeln.

Das hatte ich vorhin versucht. Doch nicht wirklich so hin bekommen.
Werde es mir morgen genauer anschauen mit der Methode die du mir genannt hast vielleicht klappt das ja :)
Danke nochmals für die schnelle nette Hilfe :)

LG
 

mrBrown

Super-Moderator
Mitarbeiter
Werde es mir morgen genauer anschauen mit der Methode die du mir genannt hast vielleicht klappt das ja :)

Ginge etwa so:
Java:
return comparing(Person::getLastName, nullsLast(naturalOrder()))
        .thenComparing(Person::getFirstName, nullsLast(naturalOrder()))
        .thenComparing(Person::getTitle, nullsLast(naturalOrder()))
        .compare(this, that);

Vergleicht erst lastName, bei Gleichheit firstName, und dann bei Gleichheit title.
Ein Attribut was null ist, ist dabei jeweils größer als eines, welches nicht null ist. Für den Title in jedem Fall nötig, bei den anderen könnte man es weglassen, wenn du sicherstellst, dass die nie null sind (dazu dann einfach das nullsLast(naturalOrder() weglassen.)

Das ganze könnte man auch noch in eine Konstante refactoren.
 

ocsme

Top Contributor
Vergleicht erst lastName, bei Gleichheit firstName, und dann bei Gleichheit title.
Ein Attribut was null ist, ist dabei jeweils größer als eines, welches nicht null ist. Für den Title in jedem Fall nötig, bei den anderen könnte man es weglassen, wenn du sicherstellst, dass die nie null sind (dazu dann einfach das nullsLast(naturalOrder() weglassen.)

Ja das mit dem Title == null macht mir bei der compareTo methode eben auch mega zu schaffen. Bekomme es einfach nicht hin.

Ich hätte gerne noch die Ordnung das erst Personen ausgegeben werden sollen dann die Gruppen. Das ganze habe ich ja auch soweit hin bekommen über die zwei Methoden:
In Person steht die compareTo Methode:
Java:
    @Override
    public int compareTo(Contact o) {
        if(o instanceof Person) {
                return lastName.compareTo(((Person) o).lastName);
        }
        else
            return -1;
    }

Da hier alles andere was keine Person ist -1 ist = Gruppen stehen die Gruppen eben hinter den Personen.
Wenn ich nun aber versuche den Title mit zu berücksichtigen bin ich einfach zu doof zu :(

Desweiteren verstehe ich jetzt auch nicht so ganz wie ich mit einem Comparator<Person> weiter kommen soll :(
Nimmt der TreeSet meine Datenstruktur zum speichern von Gruppen sowie Personen nicht die compareTo Methode zum vergleichen?

Müsste ich dann die Klasse Person als Comparator markieren und die Methode:
Java:
    @Override
    public int compare(Person o1, Person o2) {
        // TODO Auto-generated method stub
        return 0;
    }
implementieren? Die du oben ja schon hin geschrieben hast so gesehen?

Sorry doch das ganze habe ich noch nie gemacht :(

LG

Dachte mir jetzt so etwas in der Gruppe toString Methode:

Java:
public String toString() {
        Comparator<Contact> c = Comparator.comparing(Person::getLastName, nullsLast(naturalOrder()))
                .thenComparing(Person::getFirstName, nullsLast(naturalOrder()))
                .thenComparing(Person::getTitle, nullsLast(naturalOrder())));
        Collections.sort(entries, c);
        String ret = "";
        Iterator<Contact> it = entries.iterator();
        while(it.hasNext())
            ret+=it.next().toString()+"\n";
        ret+=name;
        return ret;
    }

naturalOrder() meckert er, kennt er nicht!

LG
 
Zuletzt bearbeitet:

mrBrown

Super-Moderator
Mitarbeiter
Ja das mit dem Title == null macht mir bei der compareTo methode eben auch mega zu schaffen. Bekomme es einfach nicht hin.
Das ist auch recht kompliziert, du musst halt 3 Fälle abdecken, ((null,null), (null, nicht null), (nicht null, nicht null)), deshalb ist's deutlich einfacher, die schon existierenden Methoden dafür zu nutzen.


Desweiteren verstehe ich jetzt auch nicht so ganz wie ich mit einem Comparator<Person> weiter kommen soll :(
Du kannst den Comparator in compareTo nutzen, um this und die andere Person zu vergleichen.

Nimmt der TreeSet meine Datenstruktur zum speichern von Gruppen sowie Personen nicht die compareTo Methode zum vergleichen?
Ja, du kannst aber auch explizit einen Comparator angeben, der dann stattdessen genutzt wird. Grad in Hinblick auch Vererbung kann das sinnvoll sein. (zB, wenn du eine weitere Implementierung von Contact einführst - du müsstest dann jede bisherige Implementierung passend zu den anderen anpassen.)

Müsste ich dann die Klasse Person als Comparator markieren und die Methode:
Nein, solltest du nicht. Meinen Codeschnipsel kannst du in die bestehende compareTo einsetzen:

Java:
@Override
public int compareTo(Contact o) {
  if(o instanceof Person) {
   Person that = (Person) o;       
   return comparing(Person::getLastName, nullsLast(naturalOrder()))
     .thenComparing(Person::getFirstName, nullsLast(naturalOrder()))
     .thenComparing(Person::getTitle, nullsLast(naturalOrder()))
     .compare(this, that);
  } 
  else
    return -1;
}

(Oder halt dem TreeSet einen Comparator mitnehmen, das kann oft praktischer sein.)
 

ocsme

Top Contributor
Wo kommt nun die comparing Methode her?
Ich dachte die wäre im Comparator?
----
Das ganze Thema überfordert mich gerade sehr :(
-----

Die naturalOrder() Methode müsste nun noch in Person rein. Denn so geht es nicht :D
Java:
            return comparing(Person::getLastName, nullsLast(Comparator.naturalOrder()))
 

mrBrown

Super-Moderator
Mitarbeiter
Wo kommt nun die comparing Methode her?
Ich dachte die wäre im Comparator?
Ist sie auch. Du kannst die ganzen statischen Methoden importieren, dann musst du nicht jedes mal die Klasse davor setzen: import static java.util.Comparator.*;

In ausgeschrieben wäre das so:
Java:
return Comparator.comparing(Person::getLastName, Comparator.nullsLast(Comparator.naturalOrder()))
        .thenComparing(Person::getFirstName, Comparator.nullsLast(Comparator.naturalOrder()))
        .thenComparing(Person::getTitle, Comparator.nullsLast(Comparator.naturalOrder()))
        .compare(this, that);

Die naturalOrder() Methode müsste nun noch in Person rein. Denn so geht es nicht :D
was meinst du damit? o_O
 

ocsme

Top Contributor
was meinst du damit? o_O

Ja ich dachte du meintest das man naturalOrder() selbst schreiben müsste.
Dann hab ich im Internet nach gelesen und gesehen das die Methode im Comparator ist.
Doch auf die Idee nullsLast im Comparator zu such bin ich nicht gekommen.

So geht es nun.

Java:
    @Override
    public int compareTo(Contact o) {
        if(o instanceof Person) {
            Person that = (Person) o; 
            return Comparator.comparing(Person::getLastName, Comparator.nullsLast(Comparator.naturalOrder()))
                    .thenComparing(Person::getFirstName, Comparator.nullsLast(Comparator.naturalOrder()))
                    .thenComparing(Person::getTitle, Comparator.nullsLast(Comparator.naturalOrder()))
                    .compare(this, that);
        }
        else
            return -1;
    }

Jetzt habe ich aber noch eine Frage, wieso Funktioniert das?
Denn Comparator.comparing "returns a Comparator<T> that compares by that sort key" wenn ich nicht ganz Falsch liege ist das ein Object und kein int Wert!
Ufff... das Thema ist ja super Umfangreich!!! Wie man das alles nur verstehen soll? :(

LG
 

mrBrown

Super-Moderator
Mitarbeiter
Jetzt habe ich aber noch eine Frage, wieso Funktioniert das?
Denn Comparator.comparing "returns a Comparator<T> that compares by that sort key" wenn ich nicht ganz Falsch liege ist das ein Object und kein int Wert!
Ja, das gibt einen Comparator zurück - guck dir aber mal die letzte Zeile des Blocks an, dort wird compare aufgerufen, und damit this und that verglichen ;)
 

ocsme

Top Contributor
guck dir aber mal die letzte Zeile des Blocks an, dort wird compare aufgerufen, und damit this und that verglichen ;)

:D haha die Wollte ich erst Weg lassen! Ich hab auch erst that gesucht! dachte das wäre ähnlich wie this eine Referenz auf irgendwas Java internes bis ich gesehen hab du hast Person that Object erstellt. :D

Das Thema macht bei mir weiterhin Gehirnmatsch :D
Ich bekomme ein Comparator zurück der den einen Wert verglichen hat nach dem obigen Kriterium dann vergleicht er diesen mit dem aufrufenden this.compare(that) <- so irgendwie?

Wie kann man das ganze den noch üben? Muss auch noch die Lambda Lernen und FunktionsInterfaces :)

LG
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
F compareTo - Sortierung nach 2 Argumenten Java Basics - Anfänger-Themen 10
Cassy3 Generics - CompareTo Java Basics - Anfänger-Themen 21
J compareTo()- und equals-Methode Java Basics - Anfänger-Themen 3
X compareTo Methode wird ignoriert Java Basics - Anfänger-Themen 7
J Hashmap langsamer als compareTo? Java Basics - Anfänger-Themen 23
B Methoden compare() und compareTo() Java Basics - Anfänger-Themen 1
P compareTo() Java Basics - Anfänger-Themen 3
C compareTo verwenden Java Basics - Anfänger-Themen 2
T Datentypen compareTo() u. equals() bei Strings Java Basics - Anfänger-Themen 3
K hashCode, compareTo vs. equals Java Basics - Anfänger-Themen 3
J Sortier alternativen mit der compareTo Methode? Java Basics - Anfänger-Themen 6
J TreeSet mit compareTo sortieren Java Basics - Anfänger-Themen 2
K compareTo(String arg) überschreiben Java Basics - Anfänger-Themen 4
N Compiler-Fehler Comparable / compareTo implementierung Java Basics - Anfänger-Themen 2
M CompareTo soll Datum sortieren Java Basics - Anfänger-Themen 2
S compareTo() und equals() Java Basics - Anfänger-Themen 6
A Objekte aus 2 Klassen mit compareTo() vergleichen Java Basics - Anfänger-Themen 7
K CompareTo zwei mal benutzen klappt nicht. Java Basics - Anfänger-Themen 2
1 HILFE! Strings mit CompareTo vergleichen Java Basics - Anfänger-Themen 3
R compareTo & equals Java Basics - Anfänger-Themen 10
T Methoden Wie compareTo() Methode implementieren? Java Basics - Anfänger-Themen 9
T Strings mit compareto vergleichen und array sortieren Java Basics - Anfänger-Themen 14
P Generischer Binärbaum (compareTo Frage) Java Basics - Anfänger-Themen 4
J Probleme mit Comparable, compareTo() Java Basics - Anfänger-Themen 2
R compareTo Liste sortieren Java Basics - Anfänger-Themen 5
L compareTo bei Strings? Java Basics - Anfänger-Themen 4
D OOP mit compareTo Array sortieren (aus zwei Klassen) Java Basics - Anfänger-Themen 3
T compareTo warum geht es nicht? Java Basics - Anfänger-Themen 2
W compareTo für 3 Strings Java Basics - Anfänger-Themen 11
M compareTo-Sortierungsproblem Java Basics - Anfänger-Themen 16
G in compareTo umschreiben Java Basics - Anfänger-Themen 4
A Die "compareTo( )" methode Java Basics - Anfänger-Themen 16
J compareTo Java Basics - Anfänger-Themen 4
G compareTo Java Basics - Anfänger-Themen 12
T Wie geht das mit compareTo Java Basics - Anfänger-Themen 2
M o.compareTo(o) Java Basics - Anfänger-Themen 13
K compareTo in Verbinug mit Arrays.sort() Java Basics - Anfänger-Themen 4
Bierhumpen compareTo. Wie setze ich es ein Java Basics - Anfänger-Themen 11
R compareTo Java Basics - Anfänger-Themen 2
D Map<String, Integer> sortieren und der reinfolge nach die Glieder abfragen Java Basics - Anfänger-Themen 3
S nach Import von jars (PLC4x) in Eclipse kann nicht mehr compiliert werden Java Basics - Anfänger-Themen 9
S Java: Wie sortiere ich eine ArrayList benutzerdefinierter Objekte nach einem bestimmten Attribut? Java Basics - Anfänger-Themen 2
M Queue-Datenstruktur: nach dem Elementen entfernen, das Ergebnis ist immer noch nicht optimal. Java Basics - Anfänger-Themen 3
N Hey Leute und zwar versuche ich gerade ein 2D Spiel zu Programmieren aber die Figur will sich nicht nach links oder rechts bewegen :( Java Basics - Anfänger-Themen 12
H Liste nach String-Länge sortieren Java Basics - Anfänger-Themen 1
I Bild richtig speichern / Hochkant im File Explorer, nach Upload vertikal Java Basics - Anfänger-Themen 9
D Wie kann man in Java nach Arrays auf Duplikate prüfen Java Basics - Anfänger-Themen 12
C Probleme mit Byte konvertieren nach int Java Basics - Anfänger-Themen 10
T sortierung der eingabe nach größe Java Basics - Anfänger-Themen 5
G Bei dynamischer Arrayliste nach jeder Auswahl Zahl entfernen Java Basics - Anfänger-Themen 3
ptcho Werte/Position nach dem Funktionsaufruf tauschen? Java Basics - Anfänger-Themen 1
K Warum wird mir hier nach dem ersten Durchlauf zwei mal "welchen Datentyp wollen sie übergeben?" ausgegeben ? Java Basics - Anfänger-Themen 1
H Cast von Float nach String klappt nicht Java Basics - Anfänger-Themen 12
W LocalDate toString und nach Split falsch "erkannt"? Java Basics - Anfänger-Themen 8
B Array nach Elementwerten sortieren? Java Basics - Anfänger-Themen 1
S Größte Zahl nach Eingabe der Zahl 0 ausgeben Java Basics - Anfänger-Themen 6
I Java Mail Timeout erst nach rund 5 Minuten? Java Basics - Anfänger-Themen 9
FireHorses Einen Command erst nach einer Chateingabe aktivieren Java Basics - Anfänger-Themen 1
izoards Sortier Algorithmus für Bounding Box Elememte Links nach Rechts und von Oben nach Unten Java Basics - Anfänger-Themen 33
Jambolo Karten sortieren nach Rang und Farbe Java Basics - Anfänger-Themen 5
Lion.King Subtraktion nach Eingabe im Terminal Java Basics - Anfänger-Themen 7
D Programmieren nach UML Java Basics - Anfänger-Themen 2
rosima26 Java nach letzter Ziffer sortieren Java Basics - Anfänger-Themen 19
H Kompliziertes Sortieren einer ArrayList mit Objekten(Sortieren nach X und Y) Java Basics - Anfänger-Themen 11
H Erste Schritte Nach einer Zahl n soll n Mal der String untereinander ausgegeben werden Java Basics - Anfänger-Themen 3
volcanos List & ArrayList nach Familiennamen abfragen Java Basics - Anfänger-Themen 57
sserio Wie kann man nach einer Klasse fragen? Java Basics - Anfänger-Themen 12
S Java Client-je nach Heap Size Größe startet Applikation oder nicht Java Basics - Anfänger-Themen 4
A String split funktioniert nicht, wenn mehr als 1 Ziffer vor dem Zeichen steht nach dem er trennen soll? Java Basics - Anfänger-Themen 4
F Suche nach betreuender Person für eine Jahresarbeit der 12. Klasse. Java Basics - Anfänger-Themen 6
F nach Methode Programm nicht beenden Java Basics - Anfänger-Themen 9
E Umlaute und Sonderzeichen werden nach der Build Project nicht richtig angezeigt Java Basics - Anfänger-Themen 2
M Bei nach oben scrollen soll Seite aktualisiert werden (Userscript mit Javascript) Java Basics - Anfänger-Themen 10
K log4j nach log4j2 überführen Java Basics - Anfänger-Themen 0
javapingu Jeglichen Inhalt einer Textdatei nach Zeile n löschen Java Basics - Anfänger-Themen 8
J Nach dem Exportieren funktioniert mein Programm nicht mehr Java Basics - Anfänger-Themen 8
P Datei einlesen, nach Begriff filtern und in Datei ausgeben. Problem Standardausgabe über Konsole Java Basics - Anfänger-Themen 19
B Array nach Wert prüfen rekursiv Java Basics - Anfänger-Themen 5
CptK For-Schleife in Thread nach jedem Durchlauf pausieren Java Basics - Anfänger-Themen 35
D Primzahlen Rechner nach Eratostenes von Kyrene Algorithmus Java Basics - Anfänger-Themen 2
rafi072001 Sortieren einer HashMap nach Values Java Basics - Anfänger-Themen 2
L Zahlungen nach Monat filtern Java Basics - Anfänger-Themen 2
J Jtable Eingabe nach Klick ausserhalb der Tabelle übernehmen Java Basics - Anfänger-Themen 6
I String nach Wort suchen Java Basics - Anfänger-Themen 6
C ArrayList sortieren nach bestimmten Buchstaben in den Wörtern Java Basics - Anfänger-Themen 13
javaluke Erste Schritte Array nach Datentyp sortieren Java Basics - Anfänger-Themen 16
D Methoden nach einer bestimmten Reihenfolge ausführen. Java Basics - Anfänger-Themen 20
idontknow707 Matrix nach z.B. Variable durchsuchen Java Basics - Anfänger-Themen 4
O 2D-Array nach einer Spalte sortieren Java Basics - Anfänger-Themen 22
I Liste gruppieren nach Monat? Java Basics - Anfänger-Themen 5
P Ein Objekt nach einem String durchsuchen? Java Basics - Anfänger-Themen 7
M Nach einer erstmaligen Eingabe, eine zweite Eingabe nur noch gegen bestätigung möglich Java Basics - Anfänger-Themen 2
D Input/Output fehlerhafter Algorithmus zum Ersetzen von Array-Werten nach logischem Schema Java Basics - Anfänger-Themen 1
C Meldung einer Klasse nach "oben" Java Basics - Anfänger-Themen 6
B Nach eingefügtem Code erkennt Compiler keine Instanzvar und meldet SyntaxError Java Basics - Anfänger-Themen 2
newcomerJava Nach doppelter Zahl eine Ausgabe Java Basics - Anfänger-Themen 10
M Anzahl Schleifendurchgänge nach x Sekunden anzeigen Java Basics - Anfänger-Themen 2
C Lotto 3, 4, 5, 6 Richtige nach x Ziehungen ermittelt.. Java Basics - Anfänger-Themen 7
G Primzahlen von Rekursiv nach Iterativ Java Basics - Anfänger-Themen 6
F JMenuItem Kann nicht nach einem String benannt werden... Java Basics - Anfänger-Themen 11

Ähnliche Java Themen

Neue Themen


Oben