Сортировка списка в Java по 2 критериям - PullRequest
13 голосов
/ 08 апреля 2011

У меня есть список объектов. Каждый объект содержит String и Date (среди прочих).

Я хочу сначала отсортировать по String, а затем по Date.

Как это можно сделать самым чистым способом?

Спасибо!

Krt_Malta

Ответы [ 6 ]

19 голосов
/ 13 марта 2016

С Java 8 это действительно просто. Учитывая

class MyClass {
    String getString() { ... }
    Date getDate() { ... }
}

Вы можете легко отсортировать список следующим образом:

List<MyClass> list = ...
list.sort(Comparator.comparing(MyClass::getString).thenComparing(MyClass::getDate));
18 голосов
/ 08 апреля 2011

Учитывая класс объекта, который выглядит следующим образом:

public class MyObject {
    public String getString() { ... }
    public Date getDate() { ... }
    ...
}

Напишите собственный класс компаратора следующим образом:

public class ObjectComparator implements Comparator{

    public int compare(Object obj1, Object obj2) {
        MyObject myObj1 = (MyObject)obj1;
        MyObject myObj2 = (MyObject)obj2;
        stringResult = myObj1.getString().compareTo(myObj2.getString());
        if (stringResult == 0) {
            // Strings are equal, sort by date
            return myObj1.getDate().compareTo(myObj2.getDate());
        }
        else {
            return stringResult;
        }
    }
}

Затем сортируйте следующим образом:

Collections.sort(objectList, new ObjectComparator());
8 голосов
/ 08 апреля 2011

Реализуйте пользовательский Comparator, используя метод compare(a,b), подобный следующему:

Обычная Ява:

 public int compare(YourObject o1, YourObject o2) {
    int result = o1.getProperty1().compareTo(o2.getProperty1()));
    if(result==0) result = o1.getProperty2().compareTo(o2.getProperty2());
    return result;
 }

С Гуава (с использованием ComparisonChain):

public int compare(YourObject o1, YourObject o2) {
    return ComparisonChain.start()
      .compare(o1.getProperty1(), o2.getProperty1())
      .compare(o1.getProperty2(), o2.getProperty2())
      .result();
 }

С Commons / Lang (с использованием CompareToBuilder):

public int compare(YourObject o1, YourObject o2) {
    return new CompareToBuilder()
      .append(o1.getProperty1(), o2.getProperty1())
      .append(o1.getProperty2(), o2.getProperty2())
      .toComparison();
 }

(Все три версии эквивалентны, но простая версия Java является наиболее многословной и, следовательно, наиболее подверженной ошибкам. Все три решения предполагают, что и o1.getProperty1(), и o1.getProperty2() реализуют Comparable).

(взято из моего предыдущего ответа )


сейчас делаем Collections.sort(yourList, yourComparator)

7 голосов
/ 08 апреля 2011

Ответ компараторов правильный, но неполный.

StringAndDateComparator implements Comparator<MyObject> {

   public int compare(MyObject first, MyObject second) {
        int result = first.getString().compareTo(second.getString());
        if (result != 0) {
            return result;
        }
        else {
            return first.getDate().compareTo(second.getDate());
        }
}

В GlazedLists есть полезный метод для объединения различных компараторов, чтобы избавить вас от написания этого шаблона.См. chainComparators метод для получения дополнительной информации.

1 голос
/ 26 июля 2017

Используя Java 8 и метод параллельной сортировки, мы также можем добиться этого следующим образом:

List<Employee> empss  = getEmployees();
Comparator<Employee> combinedComparator = Comparator.comparing(Employee::getFName)
                                                    .thenComparing(Employee::getLName);
Employee[] emppArr = employees.toArray(new Employee[empss.size()]);

//Parallel sorting
Arrays.parallelSort(emppArr, combinedComparator);
1 голос
/ 08 апреля 2011

Попробуйте этот метод:

Collections.sort(list, comparator)

Разумеется, у вас должна быть пользовательская реализация Comparator для вашего объекта, как утверждает Маной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...