I've seen plenty of ways to sort a list of objects that work fine if you know the incoming keys or at least the incoming number of keys. Problem is in my case I don't know if the user will send in 1 or 10 keys.
Currently I have a giant switch statements for each number of keys, but obviously that scales terribly. It just chains a bunch of 'thenComparing' together.
I found an example here that looks like it kind of helps but I don't know how to build a stream of comparators.
How-to chain and apply a stream of comparators?
Looking for a link or really anything pieces of information that will fill in the gaps on how to do this.
This all works from a user calling webservice where they would call it like
https://host.com/path?sort=[{"attribute1": "ASC"}, {"attribute2": "DESC"}]
Suppose you have such an entity:
static class Person {
private final int age;
private final String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}
You could define all the fields and map those to a certain comparator:
Map<String, Comparator<Person>> map = new HashMap<>();
map.put("name_ASC", Comparator.comparing(Person::getName));
map.put("name_DESC", Comparator.comparing(Person::getName).reversed());
map.put("age_ASC", Comparator.comparingInt(Person::getAge));
map.put("age_DESC", Comparator.comparingInt(Person::getAge).reversed());
And then having your input, you could do:
Comparator<Person> all = Stream.of("name_ASC", "age_DESC") // for example
.map(map::get)
.reduce(Comparator::thenComparing)
.orElse((a, b) -> 0); // or whatever you think appropriate
And sorting them after this is obviously a no brainer:
List<Person> persons = List.of(new Person(20, "Bob"), new Person(30, "Rose"));
// or Collections.sort(persons, all)
// persons.sort(all)
persons.stream().sorted(all).collect(Collectors.toList());
if you can build a list of comparators, you could use something like this:
public class MultiComparator<T> implements Comparator<T> {
private final List<Comparator<T>> comparators;
MultiComparator(List<Comparator<T>> comparators){
this.comparators = comparators;
}
@Override
public int compare(T t1, T t2) {
int r = 0;
for(Comparator c : comparators){
r = c.compare(t1,t2);
if(r != 0){
return r;
}
}
return r;
}
}
(not very java 8 ish though)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With