collections.sort定义两个元素的排序顺序?

时间:2012-01-31 20:36:59

标签: java sorting collections

我正在编写自己的比较器类PercentComparator,并按以下方式调用排序

Collections.sort(engineList, new PercentageComparator());

其中engineList是对象列表,其中每个对象具有百分比完整值,并且上面的排序功能正常工作。

现在,客户要求按产品类型和百分比按元素添加另一个订单。我们可以通过对象的两个元素来排序吗?

9 个答案:

答案 0 :(得分:4)

Collections.sort(engineList, new PercentageComparator());
Collections.sort(engineList, new ProductTypeComparator());

按产品类型和相同产品类型排序按百分比进一步排序。这是因为

  

此类保证稳定:由于排序,相同的元素不会被重新排序。

http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#sort%28java.util.List%29

答案 1 :(得分:3)

创建您自己的新Comparator,在比较产品类型后调用Percentage Comparator。

答案 2 :(得分:1)

如果我做对了:

class EngineComparator implements Comparator<Engine> {
    @Override
    public int compare(Engine o1, Engine o2) {
        int result = o1.getProdType().compareTo(o2.getProdType());
        return (result == 0) ? o1.getPercent().compareTo(o2.getPercent()) : result;
    }
}

以下是对集合进行分类的方法:


Prod-Type   Percent
=======================
  A         1
  A         2
  A         3
  B         1
  B         2
  B         3
  C         1
  C         2
  C         3

答案 3 :(得分:0)

如果要进行单独分类,请做一个单独的比较并在链中使用它们。或者你的EngineComparator(Boolean sortPercentDesc, Boolean sortProductDesc),我认为可能更好,更容易维护。

答案 4 :(得分:0)

只要所有相关(可比较)信息都包含在传递给方法的对象中,您的排序方法就可以进行任何您想要的排序。换句话说,您的可排序对象应包含所有可排序的子字段。而且你必须用一种不同的排序方法/类来处理它。

答案 5 :(得分:0)

如果第一个比较器返回0,您可以创建一个具有两个比较器的复合比较器,并从第二个比较器返回值。

您甚至可以使用N个比较器列表展开此过程并返回第一个非零结果,或者如果到达列表末尾则返回0

答案 6 :(得分:0)

通常,您的比较器会一次测试一个字段,直到存在差异。例如,如果百分比优先,后跟产品类型,并且您的类具有聪明的名称StackOverflow1:

    Comparator<StackOverflow1> COMPARATOR = new Comparator<StackOverflow1>() {

          @Override
          public int compare(StackOverflow1 o1, StackOverflow1 o2) {
             int result = Double.compare(o1.percent, o2.percent);
             if (result == 0)
                result = o1.productType - o2.productType;
                // NOTE - above line isn't really safe but used for illustration...

             // any more tests of fields here...

             return result;
          }         
   };

如果你想要大量的灵活性,一定要写出一堆独立的比较器并将它们连在一起(正如其他人所建议的那样),但很多时候都是过度杀戮 - 你只需要一个。

答案 7 :(得分:0)

首先创建另一个比较器实现,仅比较产品类型。然后打电话给:

Collections.sort(engineList, new CompoundComparator(productTypeCmp, percentageCmp));

以下是复合比较器的实现,它按照传入的顺序将比较委托给传入的比较器。

class CompoundComparator implements Comparator<Engine>{ 
    private List<Comparator> comparators;
    public CompoundComparator(Comparator<Engine> ... comparators){
       this.comparators = Arrays.asList(comparators);
    }
    public int compare(Engine o1, Engine o2){
       int cmp = 0;
       Iterator cmpIter = comparators.iterator();
       while(cmp == 0 && cmpIter.hasNext()){
          cmp = cmpIter.next().compare(o1, o2);
       }
       return cmp;
    }

}

假设对象属于Engine类型。

答案 8 :(得分:0)

要获得更通用的解决方案,请查看来自Javadocs的Apache Common的ComparatorChain

  

ComparatorChain是一个比较器,它按顺序包装一个或多个比较器。 ComparatorChain按顺序调用每个Comparator,直到1)任何单个Comparator返回非零结果(然后返回该结果),或2)ComparatorChain耗尽(并返回零)。这种类型的排序与SQL中的多列排序非常相似,这个类允许Java类在排序List时模拟这种行为。