it-swarm.com.de

Sortiere ArrayList von benutzerdefinierten Objekten nach Eigenschaft

Ich habe über das Sortieren von ArrayLists mit einem Comparator gelesen, aber in allen Beispielen benutzten die Leute compareTo, was nach einigen Recherchen 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 habe ich mich gefragt, ob ich so etwas schreiben könnte:

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);
    ...
}
1020
Samuel

Da Date implementiert Comparable hat, hat es eine compareTo-Methode, genau wie String.

So könnte Ihre benutzerdefinierte Comparator so aussehen:

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

Die compare()-Methode muss eine int zurückgeben, sodass Sie eine boolean nicht so wie Sie es ohnehin geplant hatten, direkt zurückgeben können.

Ihr Sortiercode wäre ungefähr so, wie Sie geschrieben haben:

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

Ein etwas kürzerer Weg, all dies zu schreiben, wenn Sie Ihren Vergleicher nicht wiederverwenden müssen, ist es 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());
    }
});

Seit Java-8

Sie können jetzt das letzte Beispiel in kürzerer Form schreiben, indem Sie einen Lambda-Ausdruck für die Comparator verwenden:

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

Und List verfügt über eine sort(Comparator) -Methode, sodass Sie diese noch weiter verkürzen können:

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

Dies ist eine solche verbreitete Redewendung, dass eine integrierte Methode zum Generieren einer Comparator für eine Klasse mit einem Comparable-Schlüssel vorhanden ist:

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

All dies sind gleichwertige Formen.

1396
Michael Myers

Klassen, die eine natürliche Sortierreihenfolge haben (eine Klassennummer als Beispiel), sollten die Comparable-Schnittstelle implementieren, während Klassen, die keine natürliche Sortierreihenfolge haben (beispielsweise ein Klassenlehrstuhl), mit einem Comparator (oder einem anonymen Comparator) versehen 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();
    }
}

Verwendungszweck:

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) {
        ...
    }
});
189
Björn

Um eine ArrayList zu sortieren, können Sie den folgenden Code-Ausschnitt verwenden:

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

Ja, du kannst. Es gibt zwei Optionen zum Vergleichen von Elementen, die Comparable - Schnittstelle und die Comparator - Schnittstelle.

Beide Schnittstellen ermöglichen unterschiedliches Verhalten. Mit Comparable können Sie das Objekt so verhalten, wie Sie es gerade beschrieben haben: Strings (tatsächlich implementiert String Comparable). Der zweite Komparator ermöglicht Ihnen, das zu tun, was Sie möchten. Sie würden es so machen:

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

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

Collections.sort(myArrayList);

Die Klasse Collections enthält eine Reihe dieser nützlichen, üblichen Werkzeuge.

41
aperkins

Java 8-Lambda-Ausdruck

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

OR

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

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));
29
assylias
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
CharlesW

Da Technologien täglich erscheinen, wird sich die Antwort mit der Zeit ändern. Ich habe mir LambdaJ angesehen und erscheint sehr interessant.

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

Hier haben Sie ein Beispiel:

Iterativ sortieren

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 (im Durchschnitt 2 Mal), aber können Sie einen besser lesbaren Code finden?

13
Federico Piazza

Der einfachste 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 Alphabet sortieren möchten, das nicht englische Zeichen enthält, können Sie 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());
9
Beyaz

Ab Java 8 und weiter müssen wir Collections.sort() nicht direkt verwenden. Die Variable List hat eine Standardmethode sort():

List<User> users = Arrays.asList(user1,user2,user3);
users.sort( (u1, u2) -> { 
return u1.getFirstName.compareTo(u2.getFirstName());}); 

Siehe http://visvv.blogspot.in/2016/01/sorting-objects-in-Java-8.html .

6

Funktions- und Methodenreferenz

Die Collections.sort - Methode kann eine List sortieren, indem Sie eine Comparator verwenden, die Sie übergeben. Diese Comparator kann mit der Comparator.comparing -Methode implementiert werden, bei der Sie eine Methodenreferenz als erforderliche Function übergeben können. Glücklicherweise ist der eigentliche Code viel einfacher und kürzer als diese Beschreibung.

Für Java 8:

Collections.sort(list, comparing(ClassName::getName));

oder

Collections.sort(list, comparing(ClassName::getName).reversed());

Ein anderer Weg ist

Collections.sort(list, comparing(ClassName::getName, Comparator.nullsLast(Comparator.naturalOrder())));
6
Arun

Java 8 Lambda verkürzt die Sortierung.

Collections.sort(stdList, (o1, o2) -> o1.getName().compareTo(o2.getName()));
5
javasenior

Sie können Guava ausprobieren Bestellung :

Function<Item, Date> getStartDate = new Function<Item, Date>() {
    public Date apply(Item item) {
        return item.getStartDate();
    }
};

List<Item> orderedItems = Ordering.natural().onResultOf(getStartDate).
                          sortedCopy(items);
5

Sie können mit Java 8 sortieren

yourList.sort(Comparator.comparing(Classname::getName));

or

yourList.stream().forEach(a -> a.getBObjects().sort(Comparator.comparing(Classname::getValue)));
5
Seeker

Sie können den Bean Comparator verwenden, um nach einer beliebigen Eigenschaft in Ihrer benutzerdefinierten Klasse zu sortieren.

5
camickr

Ja, das ist zum Beispiel in dieser Antwort ich sortiere nach der Eigenschaft v der Klasse IndexValue 

    // Sorting by property v using a custom comparator.
    Arrays.sort( array, new Comparator<IndexValue>(){
        public int compare( IndexValue a, IndexValue b ){
            return a.v - b.v;
        }
    });

Wenn Sie hier feststellen, erstelle ich eine anonyme innere Klasse (die Java für Schließungen ist) und leite sie direkt an die sort-Methode der Klasse Arrays weiter. 

Ihr Objekt kann auch Comparable implementieren (das ist es, was String und die meisten der Kernbibliotheken in Java tun), aber dies würde die "natürliche Sortierreihenfolge" der Klasse selbst definieren und Sie können keine neuen hinzufügen.

5
OscarRyz

Ich fand, dass die meisten, wenn nicht alle dieser Antworten auf der zugrunde liegenden Klasse (Object) basieren, um vergleichbare oder eine vergleichbare Schnittstelle für Helfer zu implementieren.

Nicht bei meiner Lösung! Mit dem folgenden Code können Sie das Feld des Objekts vergleichen, indem Sie den Namen der Zeichenfolge kennen. Sie können es leicht ändern, um den Namen nicht zu verwenden, aber dann müssen Sie ihn freigeben oder eines der Objekte erstellen, mit denen Sie vergleichen möchten.

Collections.sort(anArrayListOfSomeObjectPerhapsUsersOrSomething, new ReflectiveComparator(). new ListComparator("name"));

public class ReflectiveComparator {
    public class FieldComparator implements Comparator<Object> {
        private String fieldName;

        public FieldComparator(String fieldName){
            this.fieldName = fieldName;
        }

        @SuppressWarnings({ "unchecked", "rawtypes" })
        @Override
        public int compare(Object object1, Object object2) {
            try {
                Field field = object1.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);

                Comparable object1FieldValue = (Comparable) field.get(object1);
                Comparable object2FieldValue = (Comparable) field.get(object2);

                return object1FieldValue.compareTo(object2FieldValue);
            }catch (Exception e){}

            return 0;
        }
    }

    public class ListComparator implements Comparator<Object> {
        private String fieldName;

        public ListComparator(String fieldName) {
            this.fieldName = fieldName;
        }

        @SuppressWarnings({ "unchecked", "rawtypes" })
        @Override
        public int compare(Object object1, Object object2) {
            try {
                Field field = object1.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Comparable o1FieldValue = (Comparable) field.get(object1);
                Comparable o2FieldValue = (Comparable) field.get(object2);

                if (o1FieldValue == null){ return -1;}
                if (o2FieldValue == null){ return 1;}
                return o1FieldValue.compareTo(o2FieldValue);
            } catch (NoSuchFieldException e) {
                throw new IllegalStateException("Field doesn't exist", e);
            } catch (IllegalAccessException e) {
                throw new IllegalStateException("Field inaccessible", e);
            }
        }
    }
}
4
Kevin Parker

Diese Codeausschnitte können hilfreich sein. Wenn Sie ein Objectin meinem Fall sortieren möchten, möchte ich nach VolumeName sortieren:

public List<Volume> getSortedVolumes() throws SystemException {
    List<Volume> volumes = VolumeLocalServiceUtil.getAllVolumes();
    Collections.sort(volumes, new Comparator<Volume>() {
        public int compare(Volume o1, Volume o2) {
            Volume p1 = (Volume) o1;
            Volume p2 = (Volume) o2;
            return p1.getVolumeName().compareToIgnoreCase(
                    p2.getVolumeName());
        }
    });
    return volumes;
}

Das funktioniert. Ich benutze es in meinem jsp.

3
Laura Liparulo

Sie können sich diese Präsentation 2016 auf dem Java Forum in Stuttgart Deutschland ansehen.

Nur wenige Folien verwenden die deutsche Sprache, 99% des Inhalts ist Java-Quellcode "Englisch". mögen

someCollection.sort(
  OurCustomComparator
    .comparing(Person::getName)
    .thenComparing(Person::getId)
);

dabei verwendet OurCustomComparator Standardmethoden (und andere interessante Ideen). Wie gezeigt, führt dies zu einem sehr prägnanten Code, um eine Getter-Methode zum Sortieren auszuwählen; und super einfache Verkettung (oder Umkehrung) von Sortierkriterien. 

Wenn Sie sich für Java8 interessieren, finden Sie dort viel Material, um Ihnen den Einstieg zu erleichtern.

3
GhostCat

ihre customComparator-Klasse muss Java.util.Comparator implementieren, damit sie verwendet werden kann . Außerdem muss compare () AND equals () übergangen werden.

compare () muss die Frage beantworten: Ist Objekt 1 kleiner als, gleich oder größer als Objekt 2?

vollständige Dokumente: http://Java.Sun.com/j2se/1.5.0/docs/api/Java/util/Comparator.html

2
Vinny

Mit dieser Bibliothek hier können Sie die Liste der benutzerdefinierten Objekte in mehreren Spalten sortieren. Die Bibliothek verwendet Funktionen der Version 8.0. Muster gibt es auch dort. Hier ist ein Beispiel zu tun

SortKeys sortKeys = new SortKeys();
sortKeys.addField("firstName")
            .addField("age", true); // This (true) will sort the age descending

// Other ways to specify a property to the sorter are
//      .addField("lastName", String.class);
//      .addField("dob", Date.class, true);

// Instantiate a ListSorter
ListSorter listSorter = new ListSorter();

// Pass the data to sort (listToSort) and the "by keys" to sort (sortKeys)
List sortedList = (List<Person>) listSorter.sortList(listToSort, sortKeys);
2
Shriram M.

Neu seit 1.8 ist eine List.sort () - Methode, anstatt die Collection.sort () Zu verwenden.

Hier ist ein Codeausschnitt, der die List.sort () - Funktion veranschaulicht:

List<Fruit> fruits = new ArrayList<Fruit>();
fruits.add(new Fruit("Kiwi","green",40));
fruits.add(new Fruit("Banana","yellow",100));
fruits.add(new Fruit("Apple","mixed green,red",120));
fruits.add(new Fruit("Cherry","red",10));

// a) using an existing compareto() method
fruits.sort((Fruit f1,Fruit f2) -> f1.getFruitName().compareTo(f2.getFruitName()));
System.out.println("Using String.compareTo(): " + fruits);
//Using String.compareTo(): [Apple is: mixed green,red, Banana is: yellow, Cherry is: red, Kiwi is: green]

// b) Using a comparable class
fruits.sort((Fruit f1,Fruit f2) -> f1.compareTo(f2));  
System.out.println("Using a Comparable Fruit class (sort by color): " + fruits);
// Using a Comparable Fruit class (sort by color): [Kiwi is green, Apple is: mixed green,red, Cherry is: red, Banana is: yellow]

Die Fruchtklasse ist:

public class Fruit implements Comparable<Fruit>
{
    private String name;
    private String color;
    private int quantity;

    public Fruit(String name,String color,int quantity)
    { this.name = name; this.color = color; this.quantity = quantity; }

    public String getFruitName() { return name; }        
    public String getColor() { return color; }  
    public int getQuantity() { return quantity; }

    @Override public final int compareTo(Fruit f) // sorting the color
    {
        return this.color.compareTo(f.color);
    }     
    @Override public String toString()
    {   
        return (name + " is: " + color);
    }
} // end of Fruit class   
2
Norbert

Ich bevorzuge diesen Prozess:

public class SortUtil
{    
    public static <T> List<T> sort(List<T> list, String sortByProperty)
    {
            Collections.sort(list, new BeanComparator(sortByProperty));
            return list;
    }
}

List<T> sortedList = SortUtil<T>.sort(unsortedList, "startDate");

Wenn die Liste der Objekte eine Eigenschaft namens startDate enthält, rufen Sie diese immer wieder auf. Sie können sie sogar startDate.time ketten.

Dies erfordert, dass Ihr Objekt Comparable ist. Dies bedeutet, dass Sie eine compareTo-, equals- und hashCode-Implementierung benötigen.

Ja, es könnte schneller sein ... Aber jetzt müssen Sie keinen neuen Komparator für jeden Sortentyp erstellen. Wenn Sie Dev-Zeit sparen und auf Laufzeit verzichten können, sollten Sie sich für diese entscheiden.

1
DDus

Bei Verwendung von Java 8 kann Comparator in einer Zeile mit Comparator.comparing() definiert werden.

Verwenden Sie eine der folgenden Methoden:

Option 1:

listToBeSorted.sort(Comparator.comparing(CustomObject::getStartDate));

Option 2:

Collections.sort(listToBeSorted, Comparator.comparing(CustomObject::getStartDate));
0
Sahil Chhabra

Ihre benutzerdefinierte Klasse kann die Schnittstelle "Comparable" implementieren, für die die CompareTo-Methode implementiert werden muss. In der CompareTo-Methode können Sie dann definieren, was bedeutet, dass ein Objekt kleiner oder größer als das andere Objekt ist. In Ihrem Beispiel kann es ungefähr so ​​aussehen:

public class MyCustomClass implements Comparable<MyCustomClass>{

..........

 @Override
public int compareTo(MyCustomClass a) {
    if(this.getStartDate().before(a.getStartDate())){
        return -1;
    }else if(a.getStartDate().before(this.getStartDate())){
        return 1;
    }else {
        return 0;
    }
}

Eine negative Zahl bedeutet, dass this kleiner ist als das Objekt, mit dem verglichen wird. Eine positive Zahl zeigt an, dass this größer ist als das verglichen mit dem Objekt, und eine Null bedeutet, dass die Objekte gleich sind.

Sie können dann mit Collections.sort (myList) Ihre Liste sortieren, ohne einen Vergleicher eingeben zu müssen. Diese Methode hat auch den Vorteil, dass die Dinge automatisch sortiert werden, wenn Sie sortierte Auflistungsdatenstrukturen wie TreeSet oder TreeMap verwenden. 

Sie können diesen Artikel lesen, wenn Sie mehr über die Comparable-Benutzeroberfläche erfahren möchten (Offenlegung: Ich bin der Autor;)) von-Sammlungen/

0
A.Ebrahim