Frage Sortieren Sie ArrayList von benutzerdefinierten Objekten nach Eigenschaft


Ich las über das Sortieren von ArrayLists mit einem Komparator, aber in allen Beispielen, die Leute benutzten compareTo was nach einiger Forschung eine Methode für Strings ist.

Ich wollte eine ArrayList von benutzerdefinierten Objekten nach einer ihrer Eigenschaften sortieren: einem Date-Objekt (getStartDay()). Normalerweise vergleiche ich sie mit item1.getStartDate().before(item2.getStartDate()) also fragte ich mich, ob ich etwas schreiben könnte wie:

public class CustomComparator {
    public boolean compare(Object object1, Object object2) {
        return object1.getStartDate().before(object2.getStartDate());
    }
}

public class RandomName {
    ...
    Collections.sort(Database.arrayList, new CustomComparator);
    ...
}

952
2018-05-06 21:09


Ursprung


Antworten:


Schon seit Date implementiert Comparable, es hat ein compareTo Methode genau wie String tut.

Also deine Gewohnheit Comparator könnte so aussehen:

public class CustomComparator implements Comparator<MyObject> {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
}

Das compare() Methode muss einen zurückgeben int, also konnte man nicht direkt einen zurückgeben boolean als ob du es sowieso geplant hättest.

Dein Sortiercode wäre ungefähr so, wie du geschrieben hast:

Collections.sort(Database.arrayList, new CustomComparator());

Ein etwas kürzerer Weg, all dies zu schreiben, wenn Sie Ihren Vergleicher nicht wiederverwenden müssen, ist, ihn als anonyme Inline-Klasse zu schreiben:

Collections.sort(Database.arrayList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        return o1.getStartDate().compareTo(o2.getStartDate());
    }
});

Schon seit

Sie können nun das letzte Beispiel in einer kürzeren Form schreiben, indem Sie a verwenden Lambda-Ausdruck für die Comparator:

Collections.sort(Database.arrayList, 
                        (o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

Und List hat ein sort(Comparator) Methode, so können Sie dies noch weiter verkürzen:

Database.arrayList.sort((o1, o2) -> o1.getStartDate().compareTo(o2.getStartDate()));

Das ist so ein gängiges Idiom, das es gibt eine eingebaute Methode generieren Comparator für eine Klasse mit einem Comparable Schlüssel:

Database.arrayList.sort(Comparator.comparing(MyObject::getStartDate));

All dies sind gleichwertige Formen.


1305
2018-05-06 21:18



Klassen mit einer natürlichen Sortierreihenfolge (z. B. eine Klassennummer) sollten die Vergleichsschnittstelle implementieren, während Klassen ohne natürliche Sortierreihenfolge (z. B. eine Klasse Chair) mit einem Komparator (oder einem anonymen Komparator) bereitgestellt werden sollten Klasse).

Zwei Beispiele:

public class Number implements Comparable<Number> {
    private int value;

    public Number(int value) { this.value = value; }
    public int compareTo(Number anotherInstance) {
        return this.value - anotherInstance.value;
    }
}

public class Chair {
    private int weight;
    private int height;

    public Chair(int weight, int height) {
        this.weight = weight;
        this.height = height;
    }
    /* Omitting getters and setters */
}
class ChairWeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getWeight() - chair2.getWeight();
    }
}
class ChairHeightComparator implements Comparator<Chair> {
    public int compare(Chair chair1, Chair chair2) {
        return chair1.getHeight() - chair2.getHeight();
    }
}

Verwendung:

List<Number> numbers = new ArrayList<Number>();
...
Collections.sort(numbers);

List<Chair> chairs = new ArrayList<Chair>();
// Sort by weight:
Collections.sort(chairs, new ChairWeightComparator());
// Sort by height:
Collections.sort(chairs, new ChairHeightComparator());

// You can also create anonymous comparators;
// Sort by color:
Collections.sort(chairs, new Comparator<Chair>() {
    public int compare(Chair chair1, Chair chair2) {
        ...
    }
});

181
2018-05-06 21:45



Zum Sortieren eines ArrayList Sie könnten das folgende Code-Snippet verwenden:

Collections.sort(studList, new Comparator<Student>(){
    public int compare(Student s1, Student s2) {
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
    }
});

150
2018-05-06 13:50



Ja, du kannst. Beim Vergleichen von Elementen gibt es zwei Möglichkeiten Vergleichbar Schnittstelle und die Vergleicher Schnittstelle.

Beide dieser Schnittstellen ermöglichen ein unterschiedliches Verhalten. Vergleichbar ermöglicht es Ihnen, das Objekt so zu verhalten, wie Sie es gerade beschrieben haben (tatsächlich implementiert String Comparable). Der zweite, Comparator, erlaubt Ihnen zu tun, was Sie tun möchten. Du würdest es so machen:

Collections.sort(myArrayList, new MyComparator());

Dies führt dazu, dass die Methode Collections.sort den Vergleicher für seinen Sortiermechanismus verwendet. Wenn die Objekte in der ArrayList vergleichbar sind, können Sie stattdessen Folgendes tun:

Collections.sort(myArrayList);

Das Sammlungen Klasse enthält eine Reihe dieser nützlichen, gemeinsamen Werkzeuge.


40
2018-05-06 21:17



JAVA 8 Lambda-Ausdruck

Collections.sort(studList, (Student s1, Student s2) ->{
        return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
});

ODER

Comparator<Student> c = (s1, s2) -> s1.firstName.compareTo(s2.firstName);
studList.sort(c)

31
2017-09-05 13:10



Mit Java 8 können Sie eine Methodenreferenz für Ihren Vergleicher verwenden:

import static java.util.Comparator.comparing;

Collections.sort(list, comparing(MyObject::getStartDate));

26
2018-03-13 15:19



import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;

public class test {

public static class Person {
    public String name;
    public int id;
    public Date hireDate;

    public Person(String iname, int iid, Date ihireDate) {
        name = iname;
        id = iid;
        hireDate = ihireDate;
    }

    public String toString() {
        return name + " " + id + " " + hireDate.toString();
    }

    // Comparator
    public static class CompId implements Comparator<Person> {
        @Override
        public int compare(Person arg0, Person arg1) {
            return arg0.id - arg1.id;
        }
    }

    public static class CompDate implements Comparator<Person> {
        private int mod = 1;
        public CompDate(boolean desc) {
            if (desc) mod =-1;
        }
        @Override
        public int compare(Person arg0, Person arg1) {
            return mod*arg0.hireDate.compareTo(arg1.hireDate);
        }
    }
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    SimpleDateFormat df = new SimpleDateFormat("mm-dd-yyyy");
    ArrayList<Person> people;
    people = new ArrayList<Person>();
    try {
        people.add(new Person("Joe", 92422, df.parse("12-12-2010")));
        people.add(new Person("Joef", 24122, df.parse("1-12-2010")));
        people.add(new Person("Joee", 24922, df.parse("12-2-2010")));
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    Collections.sort(people, new Person.CompId());
    System.out.println("BY ID");
    for (Person p : people) {
        System.out.println(p.toString());
    }

    Collections.sort(people, new Person.CompDate(false));
    System.out.println("BY Date asc");
    for (Person p : people) {
        System.out.println(p.toString());
    }
    Collections.sort(people, new Person.CompDate(true));
    System.out.println("BY Date desc");
    for (Person p : people) {
        System.out.println(p.toString());
    }

}

}

13
2018-04-03 15:32



Da Technologien jeden Tag erscheinen, wird sich die Antwort in der Zeit ändern. Ich habe mir LambdaJ angesehen und scheint sehr interessant zu sein.

Sie können versuchen, diese Aufgaben mit zu lösen LambdaJ. Sie können es hier finden: http://code.google.com/p/lambdaj/

Hier haben Sie ein Beispiel:

Sortieren Iterativ

List<Person> sortedByAgePersons = new ArrayList<Person>(persons);
Collections.sort(sortedByAgePersons, new Comparator<Person>() {
        public int compare(Person p1, Person p2) {
           return Integer.valueOf(p1.getAge()).compareTo(p2.getAge());
        }
});

Sortiere mit Lambda

List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge()); 

Natürlich hat diese Art von Schönheit Auswirkungen auf die Leistung (durchschnittlich 2 Mal), aber können Sie einen besser lesbaren Code finden?


13
2018-03-12 17:49



Der beste einfache Weg mit JAVA 8 ist für englische alphabetische Sortierung

Klassenimplementierung

public class NewspaperClass implements Comparable<NewspaperClass>{
   public String name;

   @Override
   public int compareTo(NewspaperClass another) {
      return name.compareTo(another.name);
   }
}

Sortieren

  Collections.sort(Your List);

Wenn Sie nach einem Alphabet suchen möchten, das nicht englische Zeichen enthält, können Sie das Gebietsschema verwenden.

Klassenimplementierung

public class NewspaperClass implements Comparator<NewspaperClass> {
   public String name;
   public Boolean isUserNewspaper=false;
   private Collator trCollator = Collator.getInstance(new Locale("tr_TR"));



   @Override
   public int compare(NewspaperClass lhs, NewspaperClass rhs) {
      trCollator.setStrength(Collator.PRIMARY);
      return trCollator.compare(lhs.name,rhs.name);
   }
}

Sortieren

Collections.sort(your array list,new NewspaperClass());

7
2018-05-28 12:11