compareTo nach mehreren Kriterien

O

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

mrBrown

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

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

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.
 
O

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

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.
 
O

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

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.)
 
O

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

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
 
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

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 ;)
 
O

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
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 7
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
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
R JDK installieren Durcheinander nach installation von SE 14.02 Java Basics - Anfänger-Themen 6
P Sortieren von Listen nach Attributen Java Basics - Anfänger-Themen 3
B DateTimeFormatter nach LocalDateTime, wenn dd.MM.yyyy oder dd.MM.yyyy mm:hh Java Basics - Anfänger-Themen 5
1 main-Methode erweitern, Nachfrage nach wiedeholung Java Basics - Anfänger-Themen 2
G unklares Verhalten nach Instanzierung neuer Klasse Java Basics - Anfänger-Themen 3
S Wohin kommt das „abstract“? Vor oder nach „public“/ „private“ /... Java Basics - Anfänger-Themen 3
S Datenbank Befehl nach Login Java Basics - Anfänger-Themen 5
N Operatoren Schreibtischtest der Reihen-Suche nach Aufschluss in die Basics Java Basics - Anfänger-Themen 1
B Umstieg von C# nach Java Java Basics - Anfänger-Themen 18
Ellachen55 Wie nach häufigste Werte im Array suchen? Java Basics - Anfänger-Themen 2
M Untersuchen ob ein Graph nach entfernen einer Kante immer noch zusammenhängend ist Java Basics - Anfänger-Themen 70
N Wörter und Zahlen nach speziellen Wörtern ausgeben Java Basics - Anfänger-Themen 11
M Werte ändern sich nicht mehr nach Reset Java Basics - Anfänger-Themen 14
B Nach dem kompilieren werden Bilder nicht mehr gefunden Java Basics - Anfänger-Themen 10
X Nach einem Bruch testen ob es eine ganze Zahl ist Java Basics - Anfänger-Themen 6
B String nach erstem Leerzeichen trennen Java Basics - Anfänger-Themen 7
N Speichern von Werten in Variablen nach Schließen des Programms Java Basics - Anfänger-Themen 3
G String wird nach Einlesen aus Datei nicht erkannt Java Basics - Anfänger-Themen 3
UnknownInnocent Best Practice Algorithmus nach jedem Schritt zum Visualisieren pausieren Java Basics - Anfänger-Themen 3
O zwei Arrays nach Werten durchsuchen und zusammenfügen Java Basics - Anfänger-Themen 3
M Double Wert nach n abschneiden ohne zu runden Java Basics - Anfänger-Themen 1
C Erste Schritte Bilder nach Export anzeigen Java Basics - Anfänger-Themen 0
F Input/Output Files von A nach B kopieren Java Basics - Anfänger-Themen 11
B InputStream (PDF) nach Image (PNG / JPG) konvertieren? Java Basics - Anfänger-Themen 2
O ADT Graph nach größe Abfragen Java Basics - Anfänger-Themen 42
R Benutzereingaben als Array abspeichern nach Programmstart Java Basics - Anfänger-Themen 5
S Pane nach speziellen Child Objekten durchsuchen Java Basics - Anfänger-Themen 3
V Neue Ausgabe von toString nach Methodenaufruf Java Basics - Anfänger-Themen 9
L Arrayliste von hinten nach vorne ausgeben Java Basics - Anfänger-Themen 10
F Array nach Objektattribut durchsuchen Java Basics - Anfänger-Themen 6
M Rationale Zahl erkennen - Kurze Frage zum Restwert nach Division Java Basics - Anfänger-Themen 3
O String von vorne nach hinten an einem Zeichen Java Basics - Anfänger-Themen 10
Hanschyo Quicksort sortiert von groß nach klein Java Basics - Anfänger-Themen 3
S suche nach varible POSITION ... fuer das pixel-maennchen Java Basics - Anfänger-Themen 4
A Einträge aus Tupeln nach Regeln in Liste speichern Java Basics - Anfänger-Themen 8
B String nach HTML formatieren Java Basics - Anfänger-Themen 9
Zrebna Compiler-Fehler Java-Compiler wird nach 'javac' keyword-Eingabe nicht gestartet (Erste Übung) Java Basics - Anfänger-Themen 18
UnknownInnocent Klassen JPanel nach Ablauf der Spielzeit neuladen Java Basics - Anfänger-Themen 2
B Umbruch nach bestimmten Wort Java Basics - Anfänger-Themen 5
E Arrays nach best Muster füllen Java Basics - Anfänger-Themen 4
N Arbeitsspeicher nach kompilieren immer voller Java Basics - Anfänger-Themen 6
K String nach bestimmtem Muster parsen Java Basics - Anfänger-Themen 3
S Amazon Produktbeschreibung auslesen und nach Keywords suchen Java Basics - Anfänger-Themen 2
M Scanner-Eingabe nach gewissem Zeitraum überprüfen Java Basics - Anfänger-Themen 2
J variablePathPart ändern nach dem Ordner abgearbeitet worden ist Java Basics - Anfänger-Themen 1
B Wie kann ich die Buchstaben sortieren nach der Höhe der Zahlen Java Basics - Anfänger-Themen 14
J GUI wird direkt nach dem erstellen weiß übermalt Java Basics - Anfänger-Themen 3
L Programm zur Codieren nach Rotx Java Basics - Anfänger-Themen 1
S Nach dem Herüberschieben eines Arrays zwischen 2 Frames öffnet sich das Frame nicht mehr Java Basics - Anfänger-Themen 12
A ArrayList - size() nur nach bestimmtem index anzeigen lassen Java Basics - Anfänger-Themen 13
M Array nach String durchsuchen und zurückgeben Java Basics - Anfänger-Themen 16
W Wie lasse ich meine Ausgabe nach dem Lesen verschwinden ? Java Basics - Anfänger-Themen 1
F Liste nach einer Variablen sortieren Java Basics - Anfänger-Themen 6
S String trennen nach beliebigen Zeichen Java Basics - Anfänger-Themen 3
D Ich suche nach einer Möglickeit den Webseiten Inhalt per Java zu analysieren Automatisch Java Basics - Anfänger-Themen 3
B String: suche nach Wörter und in List<String> speichern Java Basics - Anfänger-Themen 3
O Array nach gleichen Zahlen prüfen und ausgeben Java Basics - Anfänger-Themen 6

Ähnliche Java Themen

Anzeige

Neue Themen


Oben