I have the issue with Java sort. In SQL, I can sort independently on each field. I need something similar in Java.
SELECT * FROM Stuff ORDER BY name ASC,last_name DSC;
When using sort(Comparator.comparing(Stuff::getName).thenComparing(Stuff::getLastName).reversed()
I get the whole sort reversed, and I want only for the second sort to be in reversed order. Is there a library for it, or a simple way to solve that?
CodePudding user response:
There's an overload of thenComparing()
which takes a Comparator
so you can compose them as wanted. Actually, thenComparing(function)
is just a convenience method for thenComparing(comparing(function))
Thus you can use this:
Comparator.comparing(Stuff::getName)
.thenComparing(Comparator.comparing(Stuff::getLastName).reversed())
Which is equal to
Comparator<Stuff> nameAscComparator = Comparator.comparing(Stuff::getName);
Comparator<Stuff> lastNameDescComparator = Comparator.comparing(Stuff::getLastName).reversed();
Comparator<Stuff> combined = nameAscComparator.thenComparing(lastNameDescComparator);
CodePudding user response:
I always have the same problem. So I defined three helper methods (orderBy
, asc
and desc
) to simply describe comparators.
@SafeVarargs
public static <T> Comparator<T> orderBy(Comparator<T> first, Comparator<? super T>... rest) {
for (Comparator<? super T> e : rest)
first = first.thenComparing(e);
return first;
}
public static <T, U extends Comparable<? super U>> Comparator<T> asc(Function<? super T, ? extends U> f) {
return Comparator.comparing(f);
}
public static <T, U extends Comparable<? super U>> Comparator<T> desc(Function<? super T, ? extends U> f) {
return Collections.reverseOrder(Comparator.comparing(f));
}
Here's an example usage:
public static void main(String[] args) {
List<Stuff> list = Arrays.asList(
new Stuff("A", "a"),
new Stuff("B", "b"),
new Stuff("A", "c"));
list.sort(orderBy(asc(Stuff::getName), desc(Stuff::getLastName)));
list.forEach(System.out::println);
}
output:
Stuff [name=A, lastName=c]
Stuff [name=A, lastName=a]
Stuff [name=B, lastName=b]
If you want to sort by a single property, you can also do something like list.sort(desc(Stuff::getLastName))
without orderBy()
.