Как отсортировать список объектов по полю
Короткий ответ
Передайте в sort() компаратор, созданный Comparator.comparing() по нужному полю:
record User(String name, int age) {}
void main() {
var users = new ArrayList<>(List.of(
new User("Anna", 30),
new User("Oleg", 25),
new User("Boris", 41)));
users.sort(Comparator.comparing(User::age));
IO.println(users);
}Результат:
[User[name=Oleg, age=25], User[name=Anna, age=30], User[name=Boris, age=41]]По убыванию
reversed() разворачивает порядок компаратора:
record User(String name, int age) {}
void main() {
var users = new ArrayList<>(List.of(new User("Anna", 30), new User("Oleg", 25), new User("Boris", 41)));
users.sort(Comparator.comparing(User::age).reversed());
users.forEach(user -> IO.println(user.name() + " " + user.age()));
}Результат:
Boris 41
Anna 30
Oleg 25По строковому полю
Строки сравниваются по алфавиту. Для числовых полей лучше comparingInt() — он не упаковывает числа в объекты:
record Product(String title, int stock) {}
void main() {
var products = new ArrayList<>(List.of(new Product("tea", 2), new Product("coffee", 5)));
products.sort(Comparator.comparing(Product::title));
IO.println(products);
products.sort(Comparator.comparingInt(Product::stock));
IO.println(products);
}Результат:
[Product[title=coffee, stock=5], Product[title=tea, stock=2]]
[Product[title=tea, stock=2], Product[title=coffee, stock=5]]Без изменения списка
sort() меняет сам список. Поток со sorted() возвращает новый:
record User(String name, int age) {}
void main() {
var users = List.of(new User("Anna", 30), new User("Oleg", 25));
var byAge = users.stream().sorted(Comparator.comparing(User::age)).toList();
IO.println(users.getFirst().name());
IO.println(byAge.getFirst().name());
}Результат:
Anna
OlegЧастая ошибка
Сортировать список из List.of(). Он неизменяемый, поэтому sort() выбрасывает исключение:
void main() {
var names = List.of("Oleg", "Anna");
names.sort(Comparator.naturalOrder());
}Результат:
Exception in thread "main" java.lang.UnsupportedOperationExceptionСначала скопируйте его в new ArrayList<>(...) или используйте stream().sorted().
Функции из этого ответа
- Comparator.comparing() — Создаёт компаратор, который сравнивает объекты по одному полю.
- List.sort() — Сортирует список на месте по заданному правилу.
- Comparator.thenComparing() — Добавляет второй критерий сортировки — для объектов, равных по первому.
- Comparator.reversed() — Возвращает компаратор с обратным порядком. Для естественного порядка есть Comparator.reverseOrder().