Comparator.comparing().reversed() reverses all the earlier comparators?

Aashish Pawar :

I have a list of Triple which is an user-defined class. When I sort it using Comparator it shows weird behavior.

Consider this snippet -

List<Triple> list = new ArrayList<>();
list.add(new Triple(1,12,13)); //adding values to list
list.add(new Triple(11,3,31));
list.add(new Triple(16,6,32));
list.add(new Triple(16,8,32));
list.add(new Triple(16,7,32));
list.add(new Triple(16,9,32));
list.add(new Triple(16,5,32));
list.add(new Triple(7,21,0));
list.add(new Triple(6,22,12));
list.add(new Triple(4,22,13));
list.add(new Triple(2,77,3));
list.add(new Triple(1,8,30));

Sort Using Comparator

 list.sort(
 Comparator.comparingInt(Triple::getA)
.thenComparingInt(Triple::getB)
.thenComparing(Triple::getC));
 list.forEach(e->System.out.printf("(%d,%d,%d) ",e.getA(),e.getB(),e.getC()));
 System.out.println();
//sort A descending if for same A ascending B and for same B ascending C
 list.sort(
Comparator.comparingInt(Triple::getA).reversed()
.thenComparingInt(Triple::getB)
.thenComparing(Triple::getC));
 list.forEach(e->System.out.printf("(%d,%d,%d) ",e.getA(),e.getB(),e.getC()));
 System.out.println();
//sort A ascending if for same A descending B and for same B ascending C
list.sort(
Comparator.comparingInt(Triple::getA)
.thenComparingInt(Triple::getB)
.reversed()
.thenComparing(Triple::getC));
list.forEach(e->System.out.printf("(%d,%d,%d) ",e.getA(),e.getB(),e.getC()));
System.out.println();
//sort A ascending if for same A ascending B and for same B descending C
list.sort(
Comparator.comparingInt(Triple::getA)
.thenComparingInt(Triple::getB)
.thenComparing(Triple::getC)
.reversed());
list.forEach(e->System.out.printf("(%d,%d,%d) ",e.getA(),e.getB(),e.getC()));

I expect the output as the list as I stated in comments -

But the output is


(16,5,32) (16,6,32) (16,7,32) (16,8,32) (16,9,32) (11,3,31) (7,21,0) (6,22,12) (4,22,13) (2,77,3) (1,8,30) (1,12,13)

(16,9,32) (16,8,32) (16,7,32) (16,6,32) (16,5,32) (11,3,31) (7,21,0) (6,22,12) (4,22,13) (2,77,3) (1,12,13) (1,8,30)

(16,9,32) (16,8,32) (16,7,32) (16,6,32) (16,5,32) (11,3,31) (7,21,0) (6,22,12) (4,22,13) (2,77,3) (1,12,13) (1,8,30)

So reversed() method reversed the earlier comparator conditions.

For your information, Triple is just class with Three variables and get set methods.

michalk :

Since you define a comparator like Comparator.comparingInt(Triple::getA) .thenComparingInt(Triple::getB) this returns a new Comparator object that contains both previous ways of comparing the object. If you then call reversed on this Comparator it returns new Comparator which reverses this Comparator - so in this case both previous conditions will be reversed.

If you want to reverse one of your comparators in the chain you can use something like :

.thenComparing(Triple::getB, Comparator.reverseOrder())

So one of your comparators can look like :

Comparator.comparingInt(Triple::getA)
                        .thenComparing(Triple::getB, Comparator.reverseOrder())
                        .thenComparing(Triple::getC)

This will only reverse B property sorting condition.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=139533&siteId=1