【问题标题】:Sorting with collections in java在java中使用集合排序
【发布时间】:2010-09-28 03:41:21
【问题描述】:

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

我有一个 HashMap,其中包含如下内容

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

QuoteBean 基本上是一个具有 setter 和 getter 方法的属性的 java bean 如下所示。

//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 对象的集合。 我想在将 bean 发送给客户端之前对其进行排序。 现在我可以使用比较器接口并对其进行排序.. 但问题是排序标准经常变化。 我的意思是有时客户想要用符号排序,有时客户想要改变有时总收益。 标准经常变化。 有没有办法将“比较”函数编写为重载并且满足所有条件...

有什么好办法解决这个问题吗..

如果有人能回复这个话题,我将不胜感激

谢谢,

【问题讨论】:

    标签: java sorting collections


    【解决方案1】:

    是的。实现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;
          }
      }
      

      这样您可以使用任何您想要的比较器,甚至可以使用多个比较器,它们将以正确的顺序执行。

      【讨论】:

      • @Colin Hebert 当你说多重实现时..介意举个例子或 pusdo 代码你是什么意思..
      • @Colin Hebert 可能介意用一个例子来解释动态实现......
      • @user436175,现在有一个例子。但是在重新阅读原始问题之后,我可能误解了这个问题。我以为您还想同时比较不同的元素。但它仍然回答了这个问题:)
      • 公共类 DynamicComparator 实现 Comparator{}
      • 不知道为什么我会得到一个名为 classcast 异常的异常
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        最好的解决方案是使用 apache commons 中的 beancomparator 对象。你可以做类似的事情

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

        或者你可以直接做一个

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

        【讨论】:

          猜你喜欢
          • 2018-01-02
          • 1970-01-01
          • 2010-09-29
          • 2013-04-30
          • 2012-06-30
          • 1970-01-01
          • 2019-04-24
          相关资源
          最近更新 更多