How to sort a list of objects by a field
Short answer
Pass sort() a comparator created by Comparator.comparing() for the field you need:
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);
}Output:
[User[name=Oleg, age=25], User[name=Anna, age=30], User[name=Boris, age=41]]Descending order
reversed() flips the comparator's order:
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()));
}Output:
Boris 41
Anna 30
Oleg 25By a string field
Strings are compared alphabetically. For number fields comparingInt() is better — it does not box the numbers:
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);
}Output:
[Product[title=coffee, stock=5], Product[title=tea, stock=2]]
[Product[title=tea, stock=2], Product[title=coffee, stock=5]]Without changing the list
sort() changes the list itself. A stream with sorted() returns a new one:
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());
}Output:
Anna
OlegCommon mistake
Sorting a list made with List.of(). It is unmodifiable, so sort() throws:
void main() {
var names = List.of("Oleg", "Anna");
names.sort(Comparator.naturalOrder());
}Output:
Exception in thread "main" java.lang.UnsupportedOperationExceptionCopy it into new ArrayList<>(...) first or use stream().sorted().
Functions used in this recipe
- Comparator.comparing() — Creates a comparator that compares objects by one key.
- List.sort() — Sorts a list in place using a given rule.
- Comparator.thenComparing() — Adds a second sort criterion — for objects equal by the first one.
- Comparator.reversed() — Returns a comparator with the opposite order. For the natural order there is Comparator.reverseOrder().