简体   繁体   中英

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,

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;
 }

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.

您将必须针对每种情况编写一个比较器,并且可以根据客户要求选择比较器。

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"));

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