简体   繁体   中英

Using Comparable Inteface for sorting both Ascending and Descending

I have a class called NewsItem in my project. I want to sort an ArrayList of NewsItem in both ways Descending and Ascending as the user wants. Problem is I am using Comparable interface and I either return an int with Ascending condition or Descending condition and the other one is commented. How can I tell the Collections.sort() method to give me Ascending or Descending sorted List. Here's my code.

@Override
public int compareTo(NewsItem compNews) {
    int compTime=((NewsItem )compNews).getNewsTime();
    /* For Ascending order*/
    return this.NewsTime-compTime;

    /* For Descending order do like this */
    //return compTime-this.NewsTime;
}

Now here Descending one is commented so I can use one of it. I could use a static boolean in this class to either use one of these conditions. But since i'm serializing this class, I have not used any static variables in this class and have refrained from doing so. Any help is appreciated.

You class should have only 1 natural order. But this doesn't mean that a list of your class should have the same order.

When sorting your list using Collections.sort , you can also pass a comparator that changes how this sort method sees your class.

An example:

Collections.sort(yourList, new Comparator<NewsItem>(){
    public void compare(NewsItem o1, NewsItem o2) {
        return o2.compareTo(o1);
    }
});

This instructs the sorting method to do the reverse of the method implemented in the main class.

Notice that when Java 8 comes out for android, you can use the shorter Collections.sort(yourList, Comparator.reverseOrder()) instead.

In java you can sort by having elements of collection all implement Comparable interface, or by implementing Comparator class.

When you implement Comparable in elements of collection that comparators sort is used as default sort order , so with only implementing Comparable you will not be able to get both sort orders.

What I would recommend is to have two comparators and use appropriate one:

public class AccendingNewsItemComparator implements Comparator<NewsItem> {
    public int compare(NewsItem a, NewsItem b) {
        if (a.getNewsTime() < b.getNewsTime()) return -1;
        if (a.getNewsTime() > b.getNewsTime()) return +1;
        return 0;
    }
}

public class DescendingNewsItemComparator extends AccendingNewsItemComparator {
    public int compare(NewsItem a, NewsItem b) {
        int result = super.compare(a, b);
        if (result == 0) return 0;
        return -result;
    }
}

With two classes you can than have your collection sorted ascending or descending like this:

List<NewsItem> items = ... // collection to sort
boolean ascendingSort = .... // this will control sort order
Collections.sort(items, ascendingSort ? new AccendingNewsItemComparator() : new DescendingNewsItemComparator());

Fully agree with previous answer , but I have one more remark. For compare Int's you can use

Integer.compare(int value1, int value2);

@Override
public int compareTo(NewsItem compNews) {
    int compTime= ((NewsItem) compNews).getNewsTime();

    return Integer.compare(compTime, this.NewsTime);
}

I dislike using Comparable as it requires a 'natural order'. But what is a natural order? For a librarian, it's by article number. For me, it's by name. For you, it's by creation time.
Hence, 'natural order' is ambiguous.

So I'm more for using a Comparator which explicitly say what you need (and create a CompareByNewsTimeAscending and CompareByNewsTimeDescending comparator).

However, what you could also do is simply order it naturally,and then reverse the list...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM