it-swarm.com.de

So sortieren Sie die Liste der Objekte nach einer Eigenschaft

Ich habe eine einfache Klasse 

public class ActiveAlarm {
    public long timeStarted;
    public long timeEnded;
    private String name = "";
    private String description = "";
    private String event;
    private boolean live = false;
}

und List<ActiveAlarm> con. Wie sortiert man aufsteigend nach timeStarted, dann nach timeEnded? Kann jemand helfen? Ich weiß in C++ mit generischem Algorithmus und Überladungsoperator <, aber ich bin neu in Java.

124
Jennifer

Machen Sie entweder ActiveAlarm implementieren Comparable<ActiveAlarm> oder implementieren Sie Comparator<ActiveAlarm> in einer separaten Klasse. Dann ruf an:

Collections.sort(list);

oder

Collections.sort(list, comparator);

Im Allgemeinen ist es eine gute Idee, Comparable<T> zu implementieren, wenn es eine einzige "natürliche" Sortierreihenfolge gibt ... ansonsten (wenn Sie happen in einer bestimmten Reihenfolge sortieren möchten, aber möglicherweise auch eine anders)) Es ist besser, Comparator<T> zu implementieren. Diese besondere Situation könnte in beide Richtungen gehen, um ehrlich zu sein ... aber ich würde wahrscheinlich bei der flexibleren Option Comparator<T> bleiben. 

EDIT: Beispielimplementierung:

public class AlarmByTimesComparer implements Comparator<ActiveAlarm> {
  @Override
  public int compare(ActiveAlarm x, ActiveAlarm y) {
    // TODO: Handle null x or y values
    int startComparison = compare(x.timeStarted, y.timeStarted);
    return startComparison != 0 ? startComparison
                                : compare(x.timeEnded, y.timeEnded);
  }

  // I don't know why this isn't in Long...
  private static int compare(long a, long b) {
    return a < b ? -1
         : a > b ? 1
         : 0;
  }
}
130
Jon Skeet

Comparator verwenden

Zum Beispiel:

class Score {

    private String name;
    private List<Integer> scores;
    // +accessor methods
}

    Collections.sort(scores, new Comparator<Score>() {

        public int compare(Score o1, Score o2) {
            // compare two instance of `Score` and return `int` as result.
            return o2.getScores().get(0).compareTo(o1.getScores().get(0));
        }
    });

Ab Java 8 können Sie einfach einen Lambda-Ausdruck verwenden, um die Comparator-Instanz darzustellen.

Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });
107
Jigar Joshi

Java 8 und höher Antwort (Verwenden von Lambda-Ausdrücken)

In Java 8 wurden Lambda-Ausdrücke eingeführt, um dies noch einfacher zu machen! Anstatt ein Comparator () - Objekt mit seinem gesamten Gerüst zu erstellen, können Sie es wie folgt vereinfachen: (Verwenden Sie Ihr Objekt als Beispiel)

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted);

oder noch kürzer:

Collections.sort(list, Comparator.comparingInt(ActiveAlarm ::getterMethod));

Diese eine Aussage entspricht der folgenden:

Collections.sort(list, new Comparator<ActiveAlarm>() {
    @Override
    public int compare(ActiveAlarm a1, ActiveAlarm a2) {
        return a1.timeStarted - a2.timeStarted;
    }
});

Stellen Sie sich Lambda-Ausdrücke so vor, als müssten Sie nur die relevanten Teile des Codes einfügen: die Methodensignatur und das, was zurückgegeben wird.

Ein weiterer Teil Ihrer Frage war, wie Sie mit mehreren Feldern vergleichen können. Um dies mit Lambda-Ausdrücken zu tun, können Sie die Funktion .thenComparing() verwenden, um zwei Vergleiche effektiv zu einem zu kombinieren:

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted             
       .thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded)
);

Der obige Code sortiert die Liste zuerst nach timeStarted und dann nach timeEnded (für die Datensätze, die dieselbe timeStarted haben).

Noch eine letzte Anmerkung: Es ist einfach, 'lange' oder 'int'-Primitiven zu vergleichen, man kann nur eines von dem anderen subtrahieren. Wenn Sie Objekte ("Long" oder "String") vergleichen, sollten Sie den integrierten Vergleich verwenden. Beispiel:

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );

EDIT: Danke an Lukas Eder, dass er mich auf .thenComparing() function hingewiesen hat.

35
John Fowler

Wir können die Liste auf zwei Arten sortieren:

1. Using Comparator : Wenn Sie die Sortierlogik an mehreren Stellen verwenden möchten Wenn Sie die Sortierlogik an einer einzigen Stelle verwenden möchten, können Sie eine anonyme innere Klasse wie folgt schreiben oder die Komparator und verwenden Sie es an mehreren Stellen

  Collections.sort(arrayList, new Comparator<ActiveAlarm>() {
        public int compare(ActiveAlarm o1, ActiveAlarm o2) {
            //Sorts by 'TimeStarted' property
            return o1.getTimeStarted()<o2.getTimeStarted()?-1:o1.getTimeStarted()>o2.getTimeStarted()?1:doSecodaryOrderSort(o1,o2);
        }

        //If 'TimeStarted' property is equal sorts by 'TimeEnded' property
        public int doSecodaryOrderSort(ActiveAlarm o1,ActiveAlarm o2) {
            return o1.getTimeEnded()<o2.getTimeEnded()?-1:o1.getTimeEnded()>o2.getTimeEnded()?1:0;
        }
    });

Wir können eine Nullprüfung für die Eigenschaften durchführen, wenn wir 'Long' anstelle von 'Long' hätten verwenden können.

2. Using Comparable (natürliche Reihenfolge) : Wenn der Sortieralgorithmus immer bei einer Eigenschaft bleibt: Schreiben Sie eine Klasse, die 'Comparable' implementiert und die 'compareTo'-Methode überschreibt, wie unten definiert

class ActiveAlarm implements Comparable<ActiveAlarm>{

public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;

public ActiveAlarm(long timeStarted,long timeEnded) {
    this.timeStarted=timeStarted;
    this.timeEnded=timeEnded;
}

public long getTimeStarted() {
    return timeStarted;
}

public long getTimeEnded() {
    return timeEnded;
}

public int compareTo(ActiveAlarm o) {
    return timeStarted<o.getTimeStarted()?-1:timeStarted>o.getTimeStarted()?1:doSecodaryOrderSort(o);
}

public int doSecodaryOrderSort(ActiveAlarm o) {
    return timeEnded<o.getTimeEnded()?-1:timeEnded>o.getTimeEnded()?1:0;
}

}

rufen Sie die Sortiermethode auf, um basierend auf der natürlichen Reihenfolge zu sortieren

Collections.sort(list);
19
Jagadeesh

In Java8 + kann dies wie folgt in eine Zeile geschrieben werden:

collectionObjec.sort (comparator_lamda) oder comparator.comparing (CollectionType :: getterOfProperty)

code: 

ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))

oder

ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))
4
Karthikeyan
public class ActiveAlarm implements Comparable<ActiveAlarm> {
    public long timeStarted;
    public long timeEnded;
    private String name = "";
    private String description = "";
    private String event;
    private boolean live = false;

    public int compareTo(ActiveAlarm a) {
        if ( this.timeStarted > a.timeStarted )
            return 1;
        else if ( this.timeStarted < a.timeStarted )
            return -1;
        else {
             if ( this.timeEnded > a.timeEnded )
                 return 1;
             else
                 return -1;
        }
 }

Das sollte Ihnen eine ungefähre Vorstellung geben. Sobald dies erledigt ist, können Sie Collections.sort() in der Liste aufrufen. 

4
Kal

Seit Java8 kann dies mit einer Kombination aus Comparator und Lambda expressions noch sauberer erfolgen.

Zum Beispiel:

class Student{

    private String name;
    private List<Score> scores;

    // +accessor methods
}

class Score {

    private int grade;
    // +accessor methods
}

    Collections.sort(student.getScores(), Comparator.comparing(Score::getGrade);
2
Mathias G.

Guava ComparChain :

Collections.sort(list, new Comparator<ActiveAlarm>(){
            @Override
            public int compare(ActiveAlarm a1, ActiveAlarm a2) {
                 return ComparisonChain.start()
                       .compare(a1.timestarted, a2.timestarted)
                       //...
                       .compare(a1.timeEnded, a1.timeEnded).result();
            }});

In Java müssen Sie die statische Collections.sort-Methode verwenden. Hier ist ein Beispiel für eine Liste von CompanyRole-Objekten, zuerst sortiert nach Anfang und dann nach Ende. Sie können sich leicht an Ihr eigenes Objekt anpassen. 

private static void order(List<TextComponent> roles) {

    Collections.sort(roles, new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            int x1 = ((CompanyRole) o1).getBegin();
            int x2 = ((CompanyRole) o2).getBegin();

            if (x1 != x2) {
                return x1 - x2;
            } else {
                int y1 = ((CompanyRole) o1).getEnd();
                int y2 = ((CompanyRole) o2).getEnd();
                return y2 - y1;
            }
        }
    });
}
1
Richard H

Wie gesagt, können Sie sortieren nach:

  • Ihr Objekt implementieren lassen Comparable 
  • Oder übergeben Sie eine Comparator an Collections.sort

Wenn Sie beide Aktionen ausführen, wird Comparable ignoriert und Comparator verwendet. Dies hilft, dass die Wertobjekte ihre eigenen logischen Comparable-Werte haben, die für Ihr Wertobjekt die sinnvollste Sortierung sind, während jeder einzelne Anwendungsfall eine eigene Implementierung hat.

0
Alireza Fattahi

Sie können Collections.sort () aufrufen und einen Comparator übergeben, den Sie schreiben müssen, um verschiedene Eigenschaften des Objekts zu vergleichen.

0
Liv

Sie können Collections.sort verwenden und Ihre eigenen Comparator<ActiveAlarm> übergeben.

0
MarcoS