You can use Comparator.reverseOrder() to have a comparator giving the reverse of the natural ordering.
If you want to reverse the ordering of an existing comparator, you can use Comparator.reversed().
Sample code:
Stream.of(1, 4, 2, 5)
.sorted(Comparator.reverseOrder());
// stream is now [5, 4, 2, 1]
Stream.of("foo", "test", "a")
.sorted(Comparator.comparingInt(String::length).reversed());
// stream is now [test, foo, a], sorted by descending length
Answer from Tunaki on Stack OverflowYou can use Comparator.reverseOrder() to have a comparator giving the reverse of the natural ordering.
If you want to reverse the ordering of an existing comparator, you can use Comparator.reversed().
Sample code:
Stream.of(1, 4, 2, 5)
.sorted(Comparator.reverseOrder());
// stream is now [5, 4, 2, 1]
Stream.of("foo", "test", "a")
.sorted(Comparator.comparingInt(String::length).reversed());
// stream is now [test, foo, a], sorted by descending length
You can also use Comparator.comparing(Function, Comparator)
It is convenient to chain comparators when necessary, e.g.:
Comparator<SomeEntity> ENTITY_COMPARATOR =
Comparator.comparing(SomeEntity::getProperty1, Comparator.reverseOrder())
.thenComparingInt(SomeEntity::getProperty2)
.thenComparing(SomeEntity::getProperty3, Comparator.reverseOrder());
Videos
What is logic behind ordering object elements? how "(this.grade - s.grade)" if positive 1 moves "this.grade" front and puts "s.grade" next in order, why not other way around?
Using negative numbers to say "this is less than that", positive numbers to say "this is more than that" and 0 to say "these 2 things are equal" has been in many computer languages for 30+ years.
Who validates the compare result (+1, -1, 0) and then puts in ascending order / descending order respectively, is there any documentation that describes internal working of this part?
There are several internal classes that use the return value to reorder elements in arrays or collections including
Collections.sort()
Arrays.sort()
TreeSet
EDIT
To answer HOW that works you will have to look at the source code for each of the classes I listed above. Some of them are quite complicated to try to make the sorting as efficient as possible. But in general, it all boils down to code like this:
Copyif( data[i].compareTo(data[j]) > 0 ){
// swap data[i] and data[j]
}
@DavidPrun Good question. I have tried explaining this with an example.
(x,y) -> (2, 5)
Ascending Order (x.compareTo(y)):
Copyif x.compareTo(y) == 1, then x > y , since y is smaller than x, you would have to move y in front of x.
2.compareTo(5) == 1 , Then don't move 5 in front of 2.
Descending Order (y.compareTo(x)):
Copyif y.compareTo(x) == 1, then y > x , since y is greater than x, you would have to move y in front of x.
5.compareTo(2) == -1 , Move 5 in front of 2.
Basically, we will always move y in front of x, if the result of compareTo method is 1.
You can do the descending sort of a user-defined class this way overriding the compare() method,
Collections.sort(unsortedList,new Comparator<Person>() {
@Override
public int compare(Person a, Person b) {
return b.getName().compareTo(a.getName());
}
});
Or by using Collection.reverse() to sort descending as user Prince mentioned in his comment.
And you can do the ascending sort like this,
Collections.sort(unsortedList,new Comparator<Person>() {
@Override
public int compare(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
});
Replace the above code with a Lambda expression(Java 8 onwards) we get concise:
Collections.sort(personList, (Person a, Person b) -> b.getName().compareTo(a.getName()));
As of Java 8, List has sort() method which takes Comparator as parameter(more concise) :
personList.sort((a,b)->b.getName().compareTo(a.getName()));
Here a and b are inferred as Person type by lambda expression.
For whats its worth here is my standard answer. The only thing new here is that is uses the Collections.reverseOrder(). Plus it puts all suggestions into one example:
/*
** Use the Collections API to sort a List for you.
**
** When your class has a "natural" sort order you can implement
** the Comparable interface.
**
** You can use an alternate sort order when you implement
** a Comparator for your class.
*/
import java.util.*;
public class Person implements Comparable<Person>
{
String name;
int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String toString()
{
return name + " : " + age;
}
/*
** Implement the natural order for this class
*/
public int compareTo(Person p)
{
return getName().compareTo(p.getName());
}
static class AgeComparator implements Comparator<Person>
{
public int compare(Person p1, Person p2)
{
int age1 = p1.getAge();
int age2 = p2.getAge();
if (age1 == age2)
return 0;
else if (age1 > age2)
return 1;
else
return -1;
}
}
public static void main(String[] args)
{
List<Person> people = new ArrayList<Person>();
people.add( new Person("Homer", 38) );
people.add( new Person("Marge", 35) );
people.add( new Person("Bart", 15) );
people.add( new Person("Lisa", 13) );
// Sort by natural order
Collections.sort(people);
System.out.println("Sort by Natural order");
System.out.println("\t" + people);
// Sort by reverse natural order
Collections.sort(people, Collections.reverseOrder());
System.out.println("Sort by reverse natural order");
System.out.println("\t" + people);
// Use a Comparator to sort by age
Collections.sort(people, new Person.AgeComparator());
System.out.println("Sort using Age Comparator");
System.out.println("\t" + people);
// Use a Comparator to sort by descending age
Collections.sort(people,
Collections.reverseOrder(new Person.AgeComparator()));
System.out.println("Sort using Reverse Age Comparator");
System.out.println("\t" + people);
}
}