Ich habe eine Reihe von Objekten person (int age; String name;)
.
Wie kann ich dieses Array alphabetisch nach Namen und dann nach Alter sortieren?
Welchen Algorithmus würden Sie dafür verwenden?
Sie können Collections.sort
wie folgt verwenden:
private static void order(List<Person> persons) {
Collections.sort(persons, new Comparator() {
public int compare(Object o1, Object o2) {
String x1 = ((Person) o1).getName();
String x2 = ((Person) o2).getName();
int sComp = x1.compareTo(x2);
if (sComp != 0) {
return sComp;
}
Integer x1 = ((Person) o1).getAge();
Integer x2 = ((Person) o2).getAge();
return x1.compareTo(x2);
}});
}
List<Persons>
wird jetzt nach Namen und dann nach Alter sortiert.
String.compareTo
"Vergleicht zwei Zeichenfolgen lexikografisch" - aus den Dokumenten .
Collections.sort
ist eine statische Methode in der nativen Sammlungsbibliothek. Für die eigentliche Sortierung müssen Sie lediglich einen Komparator bereitstellen, der definiert, wie zwei Elemente in Ihrer Liste verglichen werden sollen: Dies wird durch die Bereitstellung einer eigenen Implementierung der compare
Methode erreicht.
Comparator
zu vermeiden, dass die Eingaben umgewandelt werden müssen.Comparable
. Siehe die Antwort von @ berry120Comparator<Person> comparator = Comparator.comparing(Person::getName).thenComparingInt(Person::getAge);
Für diejenigen, die die Java 8-Streaming-API verwenden können, gibt es einen übersichtlicheren Ansatz, der hier gut dokumentiert ist: Lambdas und Sortierung
Ich habe nach dem Äquivalent zum C # LINQ gesucht:
Ich habe den Mechanismus in Java 8 im Komparator gefunden:
Hier ist also das Snippet, das den Algorithmus demonstriert.
Schauen Sie sich den Link oben an, um eine übersichtlichere Art und eine Erklärung zu erhalten, wie die Java-Typinferenz die Definition im Vergleich zu LINQ etwas umständlicher macht.
Hier ist der vollständige Unit-Test als Referenz:
quelle
Comparator<Person> comparator = Comparator.comparing(Person::getName).thenComparing(Person::getAge);
thenComparingInt
für Alter (int)Collections.sort(people, comparator);
stattdessen einfach verwenden ?Verwenden des Java 8 Streams-Ansatzes ...
Und der Java 8 Lambda-Ansatz ...
Zuletzt...
quelle
Sie müssen Ihre eigenen implementieren
Comparator
und dann verwenden: zum BeispielIhr Komparator könnte ungefähr so aussehen:
Der Komparator vergleicht zuerst die Namen. Wenn sie nicht gleich sind, gibt er das Ergebnis des Vergleichs zurück, andernfalls gibt er das Vergleichsergebnis zurück, wenn das Alter beider Personen verglichen wird.
Dieser Code ist nur ein Entwurf: Da die Klasse unveränderlich ist, können Sie sich vorstellen, einen Singleton daraus zu erstellen und stattdessen für jede Sortierung eine neue Instanz zu erstellen.
quelle
Sie können den Java 8 Lambda-Ansatz verwenden, um dies zu erreichen. So was:
quelle
Comparable<Person>
Lassen Sie Ihre Personenklasse implementieren und dann die compareTo-Methode implementieren, zum Beispiel:Das wird zuerst nach Namen (ohne Berücksichtigung der Groß- und Kleinschreibung) und dann nach Alter sortiert. Sie können dann
Arrays.sort()
oderCollections.sort()
auf der Sammlung oder dem Array von Personenobjekten ausführen .quelle
Guava
ComparisonChain
bietet eine saubere Möglichkeit, dies zu tun. Siehe diesen Link .Ein Dienstprogramm zum Ausführen einer verketteten Vergleichsanweisung. Beispielsweise:
quelle
Sie können dies tun:
quelle
Verwendung
Comparator
und setzen Sie dann Objekte inCollection
, dannCollections.sort();
quelle
Erstellen Sie so viele Komparatoren wie nötig. Rufen Sie anschließend für jede Auftragskategorie die Methode "thenComparing" auf. Es ist eine Art von Streams. Sehen:
Look: Benutzerdefiniertes Objekt nach mehreren Feldern sortieren - Komparator (Lambda-Stream)
quelle
Ich wäre vorsichtig, wenn ich Guavas verwende,
ComparisonChain
da es eine Instanz davon pro verglichenem Element erstellt, sodass Sie sich eine Erstellung vonN x Log N
Vergleichsketten ansehen würden, um zu vergleichen, ob Sie sortieren oderN
Instanzen, wenn Sie iterieren und auf Gleichheit prüfen.Ich würde stattdessen eine Statik erstellen,
Comparator
wenn möglich mit der neuesten Java 8-API oder der Guava-Ordering
API, mit der Sie dies tun können. Hier ein Beispiel mit Java 8:So verwenden Sie die Guava-
Ordering
API: https://github.com/google/guava/wiki/OrderingExplainedquelle
compare
Methode hat nichts zu schaffen, sondern gibt eine von Singleton - InstanzenLESS
,GREATER
oder inACTIVE
Abhängigkeit vom Ergebnis des Vergleichs. Dies ist ein hochoptimierter Ansatz, der keinen Speicher- oder Leistungsaufwand verursacht.Oder Sie können die Tatsache ausnutzen, dass
Collections.sort()
(oderArrays.sort()
) stabil ist (es ordnet keine gleichwertigen Elemente neu an) und zuerst mit aComparator
nach Alter und dann mit einem anderen nach Namen sortieren.In diesem speziellen Fall ist dies keine sehr gute Idee, aber wenn Sie in der Lage sein müssen, die Sortierreihenfolge zur Laufzeit zu ändern, kann dies hilfreich sein.
quelle
Sie können den generischen seriellen Komparator verwenden, um Sammlungen nach mehreren Feldern zu sortieren.
quelle
Aktualisierte Version:
quelle
Für eine Klasse
Book
wie diese:Hauptklasse mit Scheinobjekten sortieren
quelle
Ich bin mir nicht sicher, ob es in diesem Fall hässlich ist, das Kompartiment innerhalb der Person-Klasse zu schreiben. Hat es so gefallen:
quelle