We have such a test code. It is assumed that the created classes should be sorted in the first case ( LegComparator ) by the largest number of legs, and in the second case ( TailComparator ) by the presence of tails.

In both cases, the conclusion (as I thought) should be: first the dogs, and then the kiwi.

However, it turns out the opposite. What important thing did I miss?

 import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public class Test { public static void main(String[] args) { ArrayList<Animal> any = new ArrayList<>(); any.add(new Kiwi()); any.add(new Dog()); any.add(new Kiwi()); any.add(new Dog()); Collections.sort(any, new LegComparator()); for (Animal animal : any) { System.out.println(animal); } System.out.println(); Collections.sort(any, new TailComparator()); for (Animal animal : any) { System.out.println(animal); } } static class Animal { protected int countLeg = 2; protected boolean tail = false; } static class Dog extends Animal { public Dog() { countLeg = 4; tail = true; } @Override public String toString() { return "Dog"; } } static class Kiwi extends Animal { public Kiwi() { } @Override public String toString() { return "Kiwi"; } } static class LegComparator implements Comparator<Animal> { @Override public int compare(Animal first, Animal second) { if (first.countLeg == second.countLeg) { return 0; } return first.countLeg > second.countLeg ? 1 : -1; } } static class TailComparator implements Comparator<Animal> { @Override public int compare(Animal first, Animal second) { if ((first.tail && second.tail) || !(first.tail && second.tail)) { return 0; } return first.tail ? 1 : -1; } } } 

    2 answers 2

    ... in both cases, the conclusion (as I thought) should be - first the dogs, and then the kiwi ...

    All methods that perform sorting are sorted in ascending order. Those. first, creatures with fewer legs (kiwi) will go, then with more (dogs).

    From the point of view of the Comparator contract, this means that in a sorted list for indices i, j such that i <j, it is true that comparator(a.get(i), a.get(j)) <=0

    Read more about this in the Collections.sort and Comparator documentation.

    PS TailComparator does not work correctly, because expression (first.tail && second.tail) || !(first.tail && second.tail) (first.tail && second.tail) || !(first.tail && second.tail) always true . The sequence is displayed in the correct order only because the sorting algorithm does not change the order of the elements if it cannot correctly determine the order. If you comment out the first sort, the second one will stop working.

    The compare method for tails can be implemented, for example, like this:

     public int compare(Animal first, Animal second) { return ((Boolean) first.tail).compareTo(second.tail); } 
    • "All methods that perform sorting are sorted in ascending order" .. a comparator is just the means to perform this sorting itself - keekkenen

    Sorting occurs in "ascending". In this case, it is considered that one element ( first ) is “greater” than the other ( second ), if compare(first, second) returns 1 .

    There are at least three options for how to change the order of the elements so that the dogs are up to kiwi

    1. Replace

       return first.countLeg > second.countLeg ? 1 : -1; 

      On

       return first.countLeg > second.countLeg ? -1 : 1; 

      However, this option is not suitable if you need to use this comparator and to sort in another direction.

    2. Use Collections.reverseOrder to sort in the reverse order for this comparator:

       Collections.sort(any, Collections.reverseOrder(new LegComparator())); 

      This method returns a new comparator (not always, but in this case a new one will be created), inside of which the compare(T t1, T t2) calls the original comparator as compare(t2, t1) .

    3. You can not touch the comparator at all, but expand the list after sorting:

       Collections.sort(any, new LegComparator()); Collections.reverse(any); 

    However, this requires additional (albeit linear) time to rotate the list.