2009-07-30 21 views
54

Wenn ich eine einfache Liste von Strings haben:Sortieren einer Sammlung von Objekten

List<String> stringList = new ArrayList<String>(); 

Ich kann es sortieren mit:

Collections.sort(stringList); 

Aber wenn ich eine Person Klasse:

public class Person 
{ 
    private String name; 
    private Integer age; 
    private String country; 
} 

Und eine Liste davon:

List<Person> personList = new ArrayList<Person>(); 

Und ich möchte es manchmal nach Namen sortieren, manchmal nach Alter, manchmal nach Land.

Was ist der einfachste Weg, um das zu erreichen?

Ich weiß, dass ich die vergleichbare Schnittstelle implementieren kann, aber das scheint mich zu beschränken, um es durch eine bestimmte Eigenschaft zu sortieren.

+2

vielleicht sollten Sie nicht das Adjektiv "Composite" im Titel verwenden, da es wie das Composite Pattern klingt ... – fortran

Antwort

33

Umsetzung der Comparator Schnittstelle (einmal für jede unterschiedliche Reihenfolge) und nutzen die Collections.sort() Methode, die einen Komparator als zusätzliche Parameter übernimmt.

3

Implementieren Sie 3 verschiedene Arten von Komparatoren.

Sie können den Komparator zum Sortierbefehl hinzufügen. Der von Ihnen definierte Vergleicher sortiert die Elemente nach Name, Alter oder was auch immer.

Collections.sort(list, new Comparator() { 

     public int compare(Object arg0, Object arg1) { 
      if (!(arg0 instanceof Person)) { 
       return -1; 
      } 
      if (!(arg1 instanceof Person)) { 
       return -1; 
      } 

      Person pers0 = (Person)arg0; 
      Person pers1 = (Person)arg1; 


      // COMPARE NOW WHAT YOU WANT 
      // Thanks to Steve Kuo for your comment! 
      return pers0.getAge() - pers1.getAge(); 
     } 
    }); 
+0

warum nicht parametrischen Typ für Comparator verwenden? – dfa

+1

weil ich von 1.4 komme;) –

+2

Sie könnten einfach pers0.getAge() - pers1.getAge() zurückgeben. Das wird für drei Fälle funktionieren (<, > und ==). –

2

Die Collections.sort-Methode kann mit einem zweiten Argument aufgerufen werden, bei dem es sich um den zu verwendenden Komparator handelt. Erstellen Sie 3 Komparatoren, und verwenden Sie den gewünschten Vergleich.

+2

awwww ... Komparator ... syntatic Zucker ist lecker! – basszero

+0

yup, ich denke auch so. Es sollte 'Collections.sort (Person, neuer Comparator () {' – roottraveller

48

Collections.sort kann mit einem benutzerdefinierten Vergleicher aufgerufen werden Und dieser Komparator kann implementiert werden, um das Sortieren in verschiedenen Sortierreihenfolgen zu ermöglichen. Hier ist ein Beispiel (für Ihre Person Modell - mit dem Alter als Integer):

public class FlexiblePersonComparator implements Comparator<Person> { 
    public enum Order {Name, Age, Country} 

    private Order sortingBy = Name; 

    @Override 
    public int compare(Person person1, Person person2) { 
    switch(sortingBy) { 
     case Name: return person1.name.compareTo(person2.name); 
     case Age: return person1.age.compareTo(person2.age); 
     case Country: return person1.country.compareTo(person2.country); 
    } 
    throw new RuntimeException("Practically unreachable code, can't be thrown"); 
    } 

    public void setSortingBy(Order sortBy) { 
    this.sortingBy = sortingBy; 
    } 
} 

Und Sie nutzen es so, dass (Personen unter der Annahme ist ein Feld):

public void sortPersonsBy(FlexiblePersonComparator.Order sortingBy) { 
    List<Person> persons = this.persons; // useless line, just for clarification 
    FlexiblePersonComparator comparator = new FlexiblePersonComparator(); 
    comparator.setSortingBy(sortingBy); 
    Collections.sort(persons, comparator); // now we have a sorted list 
} 
+2

+1 Ich mag die Idee eines flexiblen Komparators – dfa

+4

Sie könnten auch den SortingBy-Parameter in einem Konstruktor übergeben –

+0

[Antwort von @Yishai in diesem Post] (http://stackoverflow.com/questions/1421322/how-do-i-sort-a-list-with-multiple-sort-parameters#1421537) demonstriert elegante Verwendung von Enum für benutzerdefinierte Sortierung und gruppierte Sortierung (mehrere Argumente) – gunalmel

15

Dank des Responder. Zum Wohle anderer möchte ich ein vollständiges Beispiel hinzufügen.

Die Lösung ist die schaffen die folgenden zusätzlichen Klassen:

public class NameComparator implements Comparator<Person> 
{ 
    public int compare(Person o1, Person o2) 
    { 
     return o1.getName().compareTo(o2.getName()); 
    } 
} 

public class AgeComparator implements Comparator<Person> 
{ 
    public int compare(Person o1, Person o2) 
    { 
     return o1.getAge().compareTo(o2.getAge()); 
    } 
} 

public class CountryComparator implements Comparator<Person> 
{ 
    public int compare(Person o1, Person o2) 
    { 
     return o1.getCountry().compareTo(o2.getCountry()); 
    } 
} 

Die Liste kann dann wie folgt sortiert werden:

Collections.sort(personList, new NameComparator()); 
Collections.sort(personList, new AgeComparator()); 
Collections.sort(personList, new CountryComparator()); 
+0

Danke, Kumpel.Dieser funktionierte, +1, obwohl Sie die Komparatoren selbst nicht direkt in die Klasse implementiert haben könnten? – IMustBeSomeone

5

Sie auch die BeanComparator von Apache Commons Beanutils, wie diese verwendet werden könnten :

Collections.sort(personList, new BeanComparator("name")); 
+0

Nice one.Not gesehen, dass vorher –

0

Ich fragte eine very similar question (über Suchen und nicht Sortieren), vielleicht gibt es ein paar nützliche Informationen (ich habe am Ende eine enum verwendet, die Comparator implementiert, so übergebe ich den enum Wert als Komparator-Selektor).

0

Mit lambdaj (http://code.google.com/p/lambdaj/) können Sie erreichen, was Sie in der folgenden Art und Weise sind gefragt:

sort (person, auf (Person.class) .getName());

Sortierung (personList, on (Person.class) .getAge());

sort (personList, on (Person.class) .getCountry());

9

Die Java 8 Weg, dies zu tun, ist List.sort wie folgt zu verwenden:

personList.sort(Comparator.comparing(Person::getName)); 

Stuart Marks in seiner Antwort auf here zu zitieren.

Dies ist der große Vorteil der List.sort(cmp) Erweiterungsmethode über Collections.sort(list, cmp). Es scheint, dass dies nur ein kleiner syntaktischer Vorteil ist, der myList.sort(cmp) anstelle von Collections.sort(myList, cmp) schreiben kann. Der Unterschied besteht darin, dass myList.sort(cmp) als Schnittstellenerweiterungsmethode durch die spezifische List Implementierung überschrieben werden kann. Beispiel: ArrayList.sort(cmp) sortiert die Liste in-place mit Arrays.sort(), während die Standardimplementierung die alte copyout-sort-copyback-Methode implementiert.

Verwandte Themen