swati
swati

Reputation: 2139

Sorting with collections in java

I have a tricky question in sorting with collection.

I have a HashMap which contains some thing like the following

HashMap<String,QuoteBean> mapToSort=new HashMap<<String,QuoteBean>();

QuoteBean is basically a java bean which has properties with setter and getter methods Which looks like the following.

//class QuoteBean defination

Class QuoteBean implements Serializable{
  private BigDecimal currentPricel
  private BigDecimal  change;
  private BigDecimal TotalChange;
  private String symbol;

//with getter and setter methods  

}//end of the class

Now when i get the values from the map i usually get it like this

Collection values=mapToSort.values();//which will return all the values in the map

This values is basically a collection of QuoteBean objects. I want to sort the beans before sending it to the client. Now i can use the comparator interface and sort it .. But the problem is the sorting criteria changes frequently . I mean some time the client wants to sort with symbol,some times the client wants with change some times with total gain. The criteria changes very often. Is there a way to write the " compare " function to overload and which will satisfy all the conditions...

Is there any good way of solving this problem..

I would really appreciate if some one can reply to this topic

Thanks,

Upvotes: 0

Views: 1873

Answers (4)

mezzie
mezzie

Reputation: 1296

The best solution to this would be to use a beancomparator object from apache commons. You can do something like

BeanComparator comparator = new BeanComparator("currentPricel"); Collections.sort(yourlisthere, comparator);

or you can directly do a

Collections.sort(yourlisthere, new BeanComparator("currentPricel"));

Upvotes: 1

Colin Hebert
Colin Hebert

Reputation: 93197

You can use the Comparator and create either multiple implementations, or you can use a dynamic implementation where you change the way it works by setting parameters on it.


For the multiple implementations you can take a look at @Bozho answer.

For the dynamic implementation you could do something like that :

public class DynamicComparator implements Comparator<QuoteBean> {
    public boolean compareCurrentPricel = false;
    public boolean change = false;

    //Setters for the booleans

    @Override
    public int compare(QuoteBean b1, QuoteBean b2) {
        int currentSort = 0;
        if(compareCurrentPricel && currentSort == 0){
            currentSort = compareCurrentPrice1(b1, b2);
        }
        if(change && currentSort == 0){
            currentSort = compareChange(b1, b2);
        }
    }
}

Or even better :

public class MultipleComparators<T> implements Comparator<T> {
    public List<Comparator<? super T>> comparators;

    public MultipleComparators(List<Comparator<? super T>> comparators){
        this.comparators = comparators;
    }

    @Override
    public int compare(T b1, T b2) {
        int returned = 0;
        for(Comparator<? super T> c : comparators){
            returned = c.compare(b1, b2);
            if(returned != 0){
                break;
            }
        }
        return returned;
    }
}

This way you can use any comparator you want and even multiple comparators which will be executed in the right order.

Upvotes: 2

Bozho
Bozho

Reputation: 597422

Yes. Implement the java.util.Comparator interface and use the overloaded method: Collections.sort(list, comparator) (you will need to create a new List from the elements of the collection, for example new ArrayList(collection))

So you can have:

public CurrentPriceQuoteComparator implements Comparator<QuoteBean> {
    @Override
    public int compare(QuoteBean b1, QuoteBean b2) { // implement comparison }
}

public ChangeQuoteComparator implements Comparator<QuoteBean> {
    @Override
    public int compare(QuoteBean b1, QuoteBean b2) { // implement comparison }
}

And then use Collections.sort(list, ChangeQuoteComparator.INSTANCE);

Note that it is a good practice to declare a singleton instance of each comparator, instead of instantiating it each time:

public static final ChangeQuoteComparator INSTANCE = 
     new ChangeQuoteComparator();

To extend things a little more, you can define an enum with the different comparison types:

public enum ComparisonType {
   CHANGE, CURRENT_PRICE; // etc..
}

and define a Map to match each comparison type with the appropriate comparator:

private static final Map<ComparisonType, Comparator<QuoteBean>> comparators = 
      new HashMapMap<ComparisonType, Comparator<QuoteBean>>();

static {
   comparators.put(ComparisonType.CHANGE, ChangeQuoteComparator.INSTANCE);
   comparators.put(ComparisonType.CURENT_PRICE, 
           CurrentPriceQuoteComparator.INSTANCE);
}

and then let the client specify which comparison he'd like

 public List<QuoteBean> getOrdered(ComparisonType type, // other criteria) {
     List<QuoteBean> list = new ArrayList<QuoteBean>(getQuotesCollection());
     Collections.sort(list, comparators.get(type));
     return list;
 }

Upvotes: 6

Emil
Emil

Reputation: 13799

You will have to write a comparator each for every situation and depending on the client requirement you can choose the comparator.

Upvotes: 1

Related Questions