I would like to be able to sort a list dynamically by the various, selectable properties of an element that may be passed into a method.
For example, lets say I have a Person class:
interface Person {
String getName();
int getAge();
LocalDate getBirthDate();
}
If I want to be able to sort by name first, then by age second, I would normally do this:
Collections.sort(unsortedPersons, Comparator.comparing(Person::getFirstName).thenComparing(Person::getAge))
But what if I wanted to select those properties dynamically? How could this properly be achieved? I want to be able to have a contract similar to:
List<Person> sortedPersons = sortPersons(
List.of(person1, person2, person3),
List.of(Person::getName, Person::getAge)
);
where the first parameter is the unsorted list of persons, and the second parameter is a list of functions that will create the above comparator chain dynamically.
The problem I have is that the method references below can't resolve, likely due to the fact that the list of functions can return different types.
public static List<Person> sortPersons(List<Person> unsortedPersons, List<Function<Person, ?>> sortableproperties) {
var comparator = sortableproperties.stream()
.map(Comparator::comparing)
.reduce(Comparator::thenComparing)
.orElse(Comparator.naturalOrder());
return unsortedPersons.stream()
.sorted(comparator)
.collect(Collectors.toList());
}
Is there a more elegant way to achieve this?