Eme Emertana
Eme Emertana

Reputation: 571

change an ascending sort to descending

I have the following code to sort a list but I need to make it a descending sort,

List list = new LinkedList(thismap.entrySet());
Collections.sort(list, new Comparator() {
    public int compare(Object o1, Object o2) {
        return ((Comparable) ((Map.Entry) (o2)).getValue())
                .compareTo(((Map.Entry) (o1)).getValue());
    }
});

Map output = new LinkedHashMap();
for (Iterator it = list.iterator(); it.hasNext();) {
    Map.Entry entry = (Map.Entry) it.next();
    output.put(entry.getKey(), entry.getValue());
}

Upvotes: 1

Views: 10733

Answers (3)

Brent Worden
Brent Worden

Reputation: 10974

A common, general purpose technique is to wrap a Comparator in a reverse Comparator by simply swapping the arguments.

class ReverseComparator<T> implements Comparator<T> {

    private final Comparator target;

    public ReverseComparator(Comparator<T> target) {
        super();
        this.target = target;
    }

    public int compare(T first, T second) {
        return target.compare(second, first);
    } 
}

To use it with our example:

Comparator original = new Comparator() {
    public int compare(Object o1, Object o2) {
        return ((Comparable) ((Map.Entry) (o2)).getValue())
            .compareTo(((Map.Entry) (o1)).getValue());
    }
};

Collections.sort(list, new ReverseComparator(original));

Upvotes: 8

Stephen C
Stephen C

Reputation: 718826

The simple general answer is to use java.util.Collections.reverseOrder(Comparator).

Comparator myComparator = new Comparator() {
    public int compare(Object o1, Object o2) {
    return ((Comparable) ((Map.Entry) (o2)).getValue())
        .compareTo(((Map.Entry) (o1)).getValue());
    }
}
// ... or whatever.

Comparator myReverseComparator = Collections.reverseOrder(myComparator);

Alternatively, a specific solution would be to flip the parameters in the compare method:

Comparator myReverseComparator = new Comparator() {
    public int compare(Object o2, Object o1) {  // <== NOTE - params reversed!!
    return ((Comparable) ((Map.Entry) (o2)).getValue())
        .compareTo(((Map.Entry) (o1)).getValue());
    }
}

Note that multiplying by -1 is an incorrect solution because of the Integer.MIN_VALUE edge case. Integer.MIN_VALUE * -1 is ... Integer.MIN_VALUE

Upvotes: 6

Juvanis
Juvanis

Reputation: 25950

It's all about changing the content of the method below:

public int compare(Object o1, Object o2) 
{
    return ((Comparable) ((Map.Entry) (o2)).getValue())
           .compareTo(((Map.Entry) (o1)).getValue());
}

Return a different result than the value of the statement below:

((Comparable)((Map.Entry)(o2)).getValue()).compareTo(((Map.Entry)(o1)).getValue());

Let's say the statement above is assigned to x. Then you should return 1 if x < 0, return -1 if x > 0 and return 0 if x == 0, just inside the compare() method.

So your method could look like this:

public int compare(Object o1, Object o2) 
{
   int x = ((Comparable)((Map.Entry)(o2)).getValue())
             .compareTo(((Map.Entry)(o1)).getValue());
   if(x > 0)
     return -1;
   else if (x < 0)
     return 1;

   return 0;
}

Upvotes: 1

Related Questions