Question Trier ArrayList d'objets personnalisés par propriété


J'ai lu à propos de trier ArrayLists en utilisant un comparateur, mais dans tous les exemples utilisés par les gens compareTo ce qui, selon certaines recherches, est une méthode pour Strings.

Je voulais trier une ArrayList d'objets personnalisés par l'une de leurs propriétés: un objet Date (getStartDay()). Normalement, je les compare par item1.getStartDate().before(item2.getStartDate()) donc je me demandais si je pouvais écrire quelque chose comme:

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


origine


Réponses:


Depuis Date met en oeuvre Comparable, il a un compareTo méthode comme String Est-ce que.

Donc votre coutume Comparator pourrait ressembler à ceci:

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

le compare() méthode doit retourner un int, donc vous ne pouvez pas retourner directement un boolean comme vous prévoyiez de toute façon.

Votre code de tri serait à peu près comme vous avez écrit:

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

Une façon légèrement plus courte d'écrire tout cela, si vous n'avez pas besoin de réutiliser votre comparateur, est de l'écrire comme une classe anonyme en ligne:

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

Depuis

Vous pouvez maintenant écrire le dernier exemple sous une forme plus courte en utilisant un expression lambda pour le Comparator:

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

Et List a un sort(Comparator) méthode, de sorte que vous pouvez raccourcir encore plus loin:

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

C'est un idiome si commun qu'il y a une méthode intégrée pour générer un Comparator pour une classe avec un Comparable clé:

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

Toutes ces formes sont équivalentes.


1305
2018-05-06 21:18



Les classes qui ont un ordre de tri naturel (un numéro de classe, par exemple) devraient implémenter l'interface Comparable, tandis que les classes qui n'ont pas d'ordre de tri naturel (une classe Chair, par exemple) devraient être dotées d'un comparateur (ou d'un comparateur anonyme classe).

Deux exemples:

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();
    }
}

Usage:

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



Pour trier un ArrayList vous pouvez utiliser l'extrait de code suivant:

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



Oui, vous pouvez. Il y a deux options avec des éléments de comparaison, le Comparable interface, et le Comparateur interface.

Ces deux interfaces permettent un comportement différent. Comparable vous permet de faire agir l'objet comme vous venez de le décrire Strings (en fait, String implémente Comparable). La seconde, Comparateur, vous permet de faire ce que vous demandez de faire. Vous le feriez comme ceci:

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

Cela entraînera la méthode Collections.sort à utiliser votre comparateur pour son mécanisme de tri. Si les objets de l'outil ArrayList sont comparables, vous pouvez faire quelque chose comme ceci:

Collections.sort(myArrayList);

le Collections La classe contient un certain nombre de ces outils communs utiles.


40
2018-05-06 21:17



JAVA 8 expression lambda

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

OU

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

31
2017-09-05 13:10



Avec Java 8, vous pouvez utiliser une référence de méthode pour votre comparateur:

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