Java-Komparator, wie sortiert man nach ganzen Zahlen?

Lesezeit: 7 Minuten

Ich versuche, Komparator in Java zu lernen, und ich habe dieses großartige Beispiel online gefunden. Meine Frage ist, wie dieser Code geändert werden würde, damit die Tiernamen nach Alter und in absteigender Reihenfolge geordnet werden, sodass der Älteste der Erste und der Jüngste der Letzte ist.

class Dog implements Comparator<Dog>, Comparable<Dog>{
private String name;
private int age;
Dog(){
}

Dog(String n, int a){
  name = n;
  age = a;
}

public String getDogName(){
  return name;
}

public int getDogAge(){
  return age;
}

// Overriding the compareTo method
public int compareTo(Dog d){
  return (this.name).compareTo(d.name);
}

// Overriding the compare method to sort the age 
public int compare(Dog d, Dog d1){
  return d.age - d1.age;
}
}

public class Example{
public static void main(String args[]){
  // Takes a list o Dog objects
  List<Dog> list = new ArrayList<Dog>();

  list.add(new Dog("Shaggy",3));
  list.add(new Dog("Lacy",2));
  list.add(new Dog("Roger",10));
  list.add(new Dog("Tommy",4));
  list.add(new Dog("Tammy",1));
  Collections.sort(list);// Sorts the array list

  for(Dog a: list)//printing the sorted list of names
     System.out.print(a.getDogName() + ", ");

  // Sorts the array list using comparator
  Collections.sort(list, new Dog());
  System.out.println(" ");
  for(Dog a: list)//printing the sorted list of ages
     System.out.print(a.getDogName() +"  : "+
     a.getDogAge() + ", ");
}
}

  • Dies ist sicherlich kein gutes Beispiel, einen Hund zu verwenden, um das Alter von zwei anderen zu vergleichen, ist unglaublich schlechtes Design. Egal, ob dies nur ein kleines Beispiel dafür ist, wie das funktionieren kann. Es gibt den Leuten falsche Vorstellungen davon, wie man diese Schnittstellen richtig implementiert.

    – Kopffüßer

    22. Mai 2012 um 21:00 Uhr


Benutzer-Avatar
Jeschurun

Einfach wechseln

public int compare(Dog d, Dog d1) {
  return d.age - d1.age;
}

zu

public int compare(Dog d, Dog d1) {
  return d1.age - d.age;
}

Sie sollten sie in umgekehrter Reihenfolge des Alters sortieren, wenn Sie danach suchen.

Aktualisieren:

@Arian hat Recht in seinen Kommentaren, eine der akzeptierten Möglichkeiten, einen Komparator für einen Hund zu deklarieren, wäre, ihn als öffentliches statisches Endfeld in der Klasse selbst zu deklarieren.

class Dog implements Comparable<Dog> {
    private String name;
    private int age;

    public static final Comparator<Dog> DESCENDING_COMPARATOR = new Comparator<Dog>() {
        // Overriding the compare method to sort the age
        public int compare(Dog d, Dog d1) {
            return d.age - d1.age;
        }
    };

    Dog(String n, int a) {
        name = n;
        age = a;
    }

    public String getDogName() {
        return name;
    }

    public int getDogAge() {
        return age;
    }

    // Overriding the compareTo method
    public int compareTo(Dog d) {
        return (this.name).compareTo(d.name);
    }

}

Sie können es dann überall in Ihrem Code verwenden, wo Sie Hunde wie folgt vergleichen möchten:

// Sorts the array list using comparator
Collections.sort(list, Dog.DESCENDING_COMPARATOR);

Eine weitere wichtige Sache, die Sie bei der Implementierung von Comparable beachten sollten, ist, dass es wichtig ist, dass “comparableTo” konsistent mit “equals” funktioniert. Obwohl dies nicht erforderlich ist, kann die Nichtbeachtung zu einem seltsamen Verhalten bei einigen Auflistungen führen, z. B. bei einigen Implementierungen von Sets. Sehen Dies Post für weitere Informationen zu soliden Prinzipien der Implementierung von CompareTo.

Aktualisierung 2:
Chris hat recht, dieser Code ist anfällig für Überläufe bei großen negativen Alterswerten. Der richtige Weg, dies in Java 7 und höher zu implementieren, wäre Integer.compare(d.age, d1.age) Anstatt von d.age - d1.age.

Aktualisierung 3:
Mit Java 8 könnte Ihr Comparator viel prägnanter geschrieben werden als:

public static final Comparator<Dog> DESCENDING_COMPARATOR = 
    Comparator.comparing(Dog::getDogAge).reversed();

Die Syntax für Collections.sort bleibt gleich, aber compare kann geschrieben werden als

public int compare(Dog d, Dog d1) {
    return DESCENDING_COMPARATOR.compare(d, d1);
}

  • Es ist unwahrscheinlich, dass es hier ein Problem darstellt, aber dieser Komparator hat einen Integer-Überlauf/Unterlauf-Fehler. Wenn die Hunde alt sind Integer.MIN_VALUE und jede positive ganze Zahl (bzw Integer.MAX_VALUE und jede negative Zahl), erhalten Sie einen Umlauf und die Sortierreihenfolge wird unerwartet sein. Es scheint albern, aber ich denke, dass Programmierer darüber nachdenken sollten, selbst wenn sie das Alter von Hunden vergleichen. Versuchen Sie es mit Integer.compare (und andere ähnliche Methoden in anderen java.lang.Number Unterklassen), anstatt Ihre eigene Subtraktion durchzuführen.

    – Christoph Schultz

    28. Oktober 2016 um 13:21 Uhr

  • Kommentar für die Java 8-Lösung von Update 3: Um das Alter zu vergleichen, müssen Sie matchingInt anstelle von Comparison verwenden.

    – Croo

    13. Oktober 2020 um 14:05 Uhr

Benutzer-Avatar
Georg Thekkan

public class DogAgeComparator implements Comparator<Dog> {
    public int compare(Dog o1, Dog o2) {
        return Integer.compare(o1.getAge(), o2.getId());
    }
}

  • Könnten Sie Ihre Antwort bitte näher erläutern und die von Ihnen bereitgestellte Lösung etwas genauer beschreiben?

    – Abarison

    13. Mai 2015 um 7:53 Uhr

  • Ich nehme an, du meinst Integer.compare(o1.getDogAge(), o2.getDogAge())? Die Hundeklasse von OP hat kein getAgeund das Subtrahieren der ID vom Alter macht keinen Sinn.

    – SL Barth

    13. Mai 2015 um 9:25 Uhr

  • Dieser Code erforderte wegen Integer.compare(o1.getAge(), o2.getId()) mindestens API-Level 19. Wenn Sie es in niedrigeren API-Ebenen verwenden möchten, können Sie o1.getAge() – o2.getAge() instade verwenden

    – Stoycho Andreev

    24. August 2015 um 11:43 Uhr


  • mein Fehler, gebe Integer.compare zurück (o1.getAge(), o2.getAge());

    – Georg Thekkan

    17. Oktober 2016 um 9:19 Uhr

Benutzer-Avatar
Elias

Einfach ersetzen:

return d.age - d1.age;

Durch:

return ((Integer)d.age).compareTo(d1.age);

Oder invertieren, um die Liste umzukehren:

return ((Integer)d1.age).compareTo(d.age);

BEARBEITEN:

“Speicherproblem” behoben.
In der Tat ist die bessere Lösung, die zu ändern age Feld im Dog Klasse zu Integerweil es viele Vorteile gibt, wie z null Wahrscheinlichkeit…

  • Auf Kosten der unnötigen Erstellung von Objekten. Tun Sie dies nicht für große Datensätze, wenn Sie viel sortieren müssen. Zumal die Alternative viel einfacher ist…

    – Hat QUIT–Anony-Mousse

    22. Mai 2012 um 20:46 Uhr

  • Zumindest verwenden Integer.valueOf() Anstatt von new

    – Kopffüßer

    22. Mai 2012 um 21:00 Uhr

  • Warum nicht einfach verwenden return Integer.compare(d.age, d1.age);? Ist seit Java 7 verfügbar

    – McIntosh

    6. November 2014 um 8:00 Uhr

  • Integer.compare auf Android erfordert api >= 19

    – Jan Rabe

    10. Oktober 2016 um 15:19 Uhr

Benutzer-Avatar
Jota3

Ab Java 8 können Sie verwenden:

Comparator.comparingInt(Dog::getDogAge).reversed();

Benutzer-Avatar
Dünen

Ein einfacher Weg ist

Comparator<Dog> ageAscendingComp = ...;
Comparator<Dog> ageDescendingComp = Collections.reverseOrder(ageAscendingComp);
// then call the sort method

Nebenbei bemerkt, Dog sollte wirklich nicht implementiert werden Comparator. Es bedeutet, dass Sie seltsame Dinge tun müssen, wie z

Collections.sort(myList, new Dog("Rex", 4));
// ^-- why is a new dog being made? What are we even sorting by?!
Collections.sort(myList, myList.get(0));
// ^-- or perhaps more confusingly

Vielmehr sollten Sie Kompartoren als separate Klassen erstellen.

z.B.

public class DogAgeComparator implments Comparator<Dog> {
    public int compareTo(Dog d1, Dog d2) {
        return d1.getAge() - d2.getAge();
    }
}

Dies hat den zusätzlichen Vorteil, dass Sie den Namen der Klasse verwenden können, um anzugeben, wie der Vergleicher die Liste sortieren wird. z.B.

Collections.sort(someDogs, new DogNameComparator());
// now in name ascending order

Collections.sort(someDogs, Collections.reverseOrder(new DogAgeComparator()));
// now in age descending order

Sie sollten auch keinen Hund implementieren Comparable. Das Comparable interface wird verwendet, um anzuzeigen, dass es eine inhärente und natürliche Möglichkeit gibt, diese Objekte zu ordnen (z. B. für Zahlen und Zeichenfolgen). Dies ist bei Hundeobjekten nicht der Fall, da Sie manchmal nach Alter und manchmal nach Namen sortieren möchten.

Benutzer-Avatar
olen_garn

Wenn Sie Zugriff auf die Java 8 Comparable API haben, Comparable.comparingToInt() kann von Nutzen sein. (Sehen Vergleichbare Dokumentation zu Java 8).

Zum Beispiel ein Comparator<Dog> Sortieren Dog Nach Alter absteigende Instanzen könnten wie folgt erstellt werden:

Comparable.comparingToInt(Dog::getDogAge).reversed();

Die Funktion übernimmt ein Lambda-Mapping T zu Integer, und erstellt einen aufsteigenden Komparator. Die verkettete Funktion .reversed() verwandelt den aufsteigenden Komparator in einen absteigenden Komparator.

Hinweis: Während dies für die meisten verfügbaren Android-Versionen möglicherweise nicht nützlich ist, bin ich auf diese Frage gestoßen, als ich nach ähnlichen Informationen für eine Nicht-Android-Java-Anwendung gesucht habe. Ich dachte, es könnte für andere an der gleichen Stelle nützlich sein, zu sehen, worauf ich mich letztendlich geeinigt habe.

1091720cookie-checkJava-Komparator, wie sortiert man nach ganzen Zahlen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy