Home > Back-end >  Java sort with independent reversed
Java sort with independent reversed

Time:11-09

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().

  • Related