Сортировка ArrayList пользовательских объектов по свойству
Я прочитал о сортировке ArrayList с использованием Comparator, но во всех примерах люди использовали метод compareTo
, который, согласно некоторым источникам, предназначен для строк.
Я хотел отсортировать ArrayList кастомных объектов по одному из их свойств: объекту Date (getStartDay()
). Обычно я сравниваю их следующим образом: item1.getStartDate().before(item2.getStartDate())
. Поэтому мне стало интересно, могу ли я написать что-то вроде этого:
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);
...
}
Таким образом, возникает вопрос: как правильно реализовать кастомный компаратор для сортировки ArrayList объектов по их свойству Date? Правильный ли подход с использованием метода compare
в данном случае, и как должна выглядеть реализация сравнения в рамках Comparator?
5 ответ(ов)
Классы, которые имеют естественный порядок сортировки (например, класс Number
), должны реализовывать интерфейс Comparable
. В то время как классы, которые не имеют естественного порядка сортировки (например, класс Chair
), должны быть обеспечены компаратором (или анонимным классом компаратора).
Вот два примера:
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;
}
/* Пропускаем геттеры и сеттеры */
}
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();
}
}
Использование:
List<Number> numbers = new ArrayList<Number>();
...
Collections.sort(numbers);
List<Chair> chairs = new ArrayList<Chair>();
// Сортировка по весу:
Collections.sort(chairs, new ChairWeightComparator());
// Сортировка по высоте:
Collections.sort(chairs, new ChairHeightComparator());
// Также можно создать анонимные компараторы;
// Сортировка по цвету:
Collections.sort(chairs, new Comparator<Chair>() {
public int compare(Chair chair1, Chair chair2) {
...
}
});
Таким образом, следуя этим рекомендациям, вы сможете правильно реализовать сортировку объектов в Java в зависимости от того, имеет ли ваш класс естественный порядок или его необходимо задавать с помощью компараторов.
Чтобы отсортировать ArrayList
, можно использовать следующий фрагмент кода:
Collections.sort(studList, new Comparator<Student>(){
public int compare(Student s1, Student s2) {
return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
}
});
В этом коде используется метод Collections.sort()
, который принимает два аргумента: список, который вы хотите отсортировать (в данном случае studList
), и объект Comparator
, реализующий логику сравнения. Здесь мы сравниваем объекты типа Student
по их именам, игнорируя регистр с помощью compareToIgnoreCase()
. Это позволяет сортировать студентов по их именам без учета заглавных и строчных букв.
Лямбда-выражения в Java 8
Если вы хотите отсортировать список студентов (studList
) по имени, вы можете использовать лямбда-выражения для упрощения кода. Вот несколько способов сделать это:
Способ 1: Используя Collections.sort()
Collections.sort(studList, (Student s1, Student s2) -> {
return s1.getFirstName().compareToIgnoreCase(s2.getFirstName());
});
В этом примере мы передаем лямбда-выражение в метод Collections.sort()
, которое сравнивает имена студентов без учета регистра.
Способ 2: Используя метод sort()
на списке
Comparator<Student> c = (s1, s2) -> s1.firstName.compareTo(s2.firstName);
studList.sort(c);
Во втором примере мы создаем компаратор в виде лямбда-выражения и затем применяем его прямо к списку studList
с помощью метода sort()
.
Оба подхода позволяют удобно сортировать список студентов, используя возможности, предоставляемые Java 8. Выберите тот вариант, который лучше соответствует вашим требованиям!
В Java 8 вы можете использовать ссылку на метод для вашего компаратора следующим образом:
import static java.util.Comparator.comparing;
Collections.sort(list, comparing(MyObject::getStartDate));
Таким образом, вместо того чтобы писать анонимный класс или лямбда-выражение, вы можете использовать ссылку на метод MyObject::getStartDate
, что делает код более лаконичным и читаемым.
Поскольку технологии постоянно появляются, ответ на этот вопрос может со временем изменяться. Я взглянул на LambdaJ, и это действительно интересный инструмент.
Вы можете попробовать решить данные задачи с помощью LambdaJ. Ссылка на проект: http://code.google.com/p/lambdaj/
Вот пример:
Сортировка в итеративном стиле
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());
}
});
Сортировка с использованием лямбда-выражения
List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());
Конечно, такая красота может повлиять на производительность (в среднем в 2 раза медленнее), но разве можно найти более читаемый код?
Почему вычитание этих двух временных меток (эпохи в миллисекундах) из 1927 года даёт странный результат?
Как определить, содержится ли определенное значение в массиве в Java?
Как установить Java 8 на Mac
Сортировка Map<Key, Value> по значениям
Java 8: Преобразование List<V> в Map<K, V>