Ich möchte meine Objekte mit dem Komparator in absteigender Reihenfolge sortieren.
class Person {
private int age;
}
Hier möchte ich ein Array von Personenobjekten sortieren.
Wie kann ich das machen?
Sie können die absteigende Sortierung einer benutzerdefinierten Klasse auf diese Weise ausführen, indem Sie die compare () -Methode überschreiben.
Collections.sort(unsortedList,new Comparator<Person>() {
@Override
public int compare(Person a, Person b) {
return b.getName().compareTo(a.getName());
}
});
Oder indem Sie Collection.reverse()
absteigend als Benutzer sortieren, den Prince in seinem Kommentar erwähnt hat .
Und Sie können die aufsteigende Sortierung so machen,
Collections.sort(unsortedList,new Comparator<Person>() {
@Override
public int compare(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
});
Ersetzen Sie den obigen Code durch einen Lambda-Ausdruck (ab Java 8).
Collections.sort(personList, (Person a, Person b) -> b.getName().compareTo(a.getName()));
Ab Java 8 verfügt List über die sort () -Methode, die Comparator als Parameter verwendet (prägnanter):
personList.sort((a,b)->b.getName().compareTo(a.getName()));
Hier a
und b
werden als Personentyp durch Lambda-Ausdruck abgeleitet.
Collections.reverseOrder(...)
für absteigende Sortierung verwenden.compareToIgnoreCase
auch beim Vergleichen vonString
Objekten nützlich ist. Meistens verwende ich dies anstelle von nurcompareTo
Für was es sich hier lohnt, ist meine Standardantwort. Neu ist nur, dass Collections.reverseOrder () verwendet wird. Außerdem werden alle Vorschläge in einem Beispiel zusammengefasst:
/* ** Use the Collections API to sort a List for you. ** ** When your class has a "natural" sort order you can implement ** the Comparable interface. ** ** You can use an alternate sort order when you implement ** a Comparator for your class. */ import java.util.*; public class Person implements Comparable<Person> { String name; int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public String toString() { return name + " : " + age; } /* ** Implement the natural order for this class */ public int compareTo(Person p) { return getName().compareTo(p.getName()); } static class AgeComparator implements Comparator<Person> { public int compare(Person p1, Person p2) { int age1 = p1.getAge(); int age2 = p2.getAge(); if (age1 == age2) return 0; else if (age1 > age2) return 1; else return -1; } } public static void main(String[] args) { List<Person> people = new ArrayList<Person>(); people.add( new Person("Homer", 38) ); people.add( new Person("Marge", 35) ); people.add( new Person("Bart", 15) ); people.add( new Person("Lisa", 13) ); // Sort by natural order Collections.sort(people); System.out.println("Sort by Natural order"); System.out.println("\t" + people); // Sort by reverse natural order Collections.sort(people, Collections.reverseOrder()); System.out.println("Sort by reverse natural order"); System.out.println("\t" + people); // Use a Comparator to sort by age Collections.sort(people, new Person.AgeComparator()); System.out.println("Sort using Age Comparator"); System.out.println("\t" + people); // Use a Comparator to sort by descending age Collections.sort(people, Collections.reverseOrder(new Person.AgeComparator())); System.out.println("Sort using Reverse Age Comparator"); System.out.println("\t" + people); } }
quelle
Ich würde einen Komparator für die Personenklasse erstellen, der mit einem bestimmten Sortierverhalten parametrisiert werden kann. Hier kann ich die Sortierreihenfolge festlegen, sie kann jedoch geändert werden, um auch die Sortierung für andere Personenattribute zu ermöglichen.
public class PersonComparator implements Comparator<Person> { public enum SortOrder {ASCENDING, DESCENDING} private SortOrder sortOrder; public PersonComparator(SortOrder sortOrder) { this.sortOrder = sortOrder; } @Override public int compare(Person person1, Person person2) { Integer age1 = person1.getAge(); Integer age2 = person2.getAge(); int compare = Math.signum(age1.compareTo(age2)); if (sortOrder == ASCENDING) { return compare; } else { return compare * (-1); } } }
(Ich hoffe, es wird jetzt kompiliert. Ich habe keine IDE oder JDK zur Hand, codiert "blind".)
Bearbeiten
Dank Thomas hat der Code bearbeitet. Ich würde nicht sagen, dass die Verwendung von Math.signum gut, performant und effektiv ist, aber ich möchte daran erinnern, dass die compareTo-Methode eine beliebige Ganzzahl zurückgeben kann und das Multiplizieren mit (-1) fehlschlägt, wenn die Die Implementierung gibt Integer.MIN_INTEGER zurück ... Und ich habe den Setter entfernt, weil er billig genug ist, um einen neuen PersonComparator genau dann zu erstellen, wenn er benötigt wird.
Aber ich behalte das Boxen bei, weil es zeigt, dass ich mich auf eine vorhandene vergleichbare Implementierung verlasse. Hätte so etwas tun können,
Comparable<Integer> age1 = new Integer(person1.getAge());
aber das sah zu hässlich aus. Die Idee war, ein Muster zu zeigen, das leicht an andere Personenattribute wie Name, Geburtstag als Datum usw. angepasst werden kann.quelle
compare * (-1)
anfällig für Überlauf. Ich habe den gleichen Fehler in meinem ersten Beitrag gemacht.new Reverse(new PersonComparator())
Integer age1 = ...;
hat das Boxen über sich.String[] s = {"a", "x", "y"}; Arrays.sort(s, new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); System.out.println(Arrays.toString(s)); -> [y, x, a]
Jetzt müssen Sie den Komparator für Ihre Personenklasse implementieren. So etwas wie (in aufsteigender Reihenfolge):
compare(Person a, Person b) = a.id < b.id ? -1 : (a.id == b.id) ? 0 : 1
oderInteger.valueOf(a.id).compareTo(Integer.valueOf(b.id))
.Um Verwirrung zu vermeiden, sollten Sie einen aufsteigenden Komparator implementieren und ihn mit einem Wrapper ( wie diesem ) in einen absteigenden konvertieren
new ReverseComparator<Person>(new PersonComparator())
.quelle
-1 * Integer.MIN_VALUE == Integer.MIN_VALUE
. Welches ist nicht was du willst. Ich habe die Argumente ausgetauscht, die sowieso einfacher sind.Integer.compare
erwähnt in der Dokumentation Folgendes :The value returned is identical to what would be returned by: Integer.valueOf(x).compareTo(Integer.valueOf(y))
, damit SieInteger.compare
stattdessen verwenden können.Verwenden von Google-Sammlungen:
class Person { private int age; public static Function<Person, Integer> GET_AGE = new Function<Person, Integer> { public Integer apply(Person p) { return p.age; } }; } public static void main(String[] args) { ArrayList<Person> people; // Populate the list... Collections.sort(people, Ordering.natural().onResultOf(Person.GET_AGE).reverse()); }
quelle
package com.test; import java.util.Arrays; public class Person implements Comparable { private int age; private Person(int age) { super(); this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public int compareTo(Object o) { Person other = (Person)o; if (this == other) return 0; if (this.age < other.age) return 1; else if (this.age == other.age) return 0; else return -1; } public static void main(String[] args) { Person[] arr = new Person[4]; arr[0] = new Person(50); arr[1] = new Person(20); arr[2] = new Person(10); arr[3] = new Person(90); Arrays.sort(arr); for (int i=0; i < arr.length; i++ ) { System.out.println(arr[i].age); } } }
Hier ist eine Möglichkeit, dies zu tun.
quelle
Die Klasse java.util.Collection verfügt über eine Sortiermethode, die eine Liste und einen benutzerdefinierten Komparator verwendet . Sie können Ihren eigenen Komparator definieren, um Ihr Personenobjekt nach Belieben zu sortieren.
quelle