2010-09-27 64 views
0

我在用集合排序时遇到了棘手的问题。用java中的集合排序

我有一个包含类似下面

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

一些事情QuoteBean基本上是一个Java bean具有与setter和getter方法 它看起来像以下属性是一个HashMap。

//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 

现在,当我从图中的值,我通常把它像这样

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

这个值基本上是QuoteBean对象的集合。 我想在将它发送给客户端之前对它们进行排序。 现在我可以使用比较器接口并对其进行排序.. 但问题是频繁排序标准的变化。 我的意思是有时候客户想要用符号来排序,有时客户想要用总收益改变一些时间。 标准经常更改。 是否有写的“比较”函数重载的方法,并且将满足所有条件...

是否有解决这个问题的任何好办法..

我真的很感激,如果有一个人可以回复此话题

谢谢,

+0

大家,喜欢的JavaOne? :) – Bozho 2010-09-27 19:10:49

回答

6

是的。实现java.util.Comparator接口,并使用重载的方法:Collections.sort(list, comparator)(你需要创建从集合的元素的新List,例如new ArrayList(collection)

所以,你可以有:

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

,然后用Collections.sort(list, ChangeQuoteComparator.INSTANCE);

请注意,这是一个很好的做法,声明每个比较的单一实例,而不是每次都实例吧:

public static final ChangeQuoteComparator INSTANCE = 
    new ChangeQuoteComparator(); 

要扩展的东西多一点,可以用不同的比较类型定义一个enum

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

并定义一个Map到每个比较型与适当的比较器相匹配:

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

然后让客户指定他想要的比较

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

您可以使用Comparator并创建多个实现,或者您可以使用动态实现来更改工作方式,方法是在其上设置参数。


对于多个实现你可以看看@Bozho的答案。

对于动态执行,你可以做这样的事情:

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

甚至更​​好:

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

这种方式,你可以使用任何你想要的比较,甚至将被执行多比较按照正确的顺序。

+0

@Colin Hebert当你说multipleimplementation ..Could介意给一个例子或pusdo代码你是什么意思.. – swati 2010-09-27 19:00:50

+0

@科林赫伯特可以介意解释动态实施与一个例子... – swati 2010-09-27 19:01:54

+0

@ user436175,现在在那里就是一个例子。但是在重读了原来的问题之后,我可能会误解这个问题。我以为你也想同时在不同的元素上进行比较。但它仍然回答了这个问题:) – 2010-09-27 19:33:14

1

您必须为每种情况编写一个比较器,并根据客户要求选择比较器。

1

最好的解决方案是使用apache公共的beancomparator对象。你可以这样做

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

,或者你可以直接做

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