我写我自己的比较类调用PercentComparator
并呼吁排序如下collections.sort定义两个元素的排序顺序?
Collections.sort(engineList, new PercentageComparator());
其中engineList
为对象的列表,每个对象都有完成百分比值,高于排序功能工作正常。
现在客户要求按产品类型和百分比添加元素。我们可以按对象的两个元素排序吗?
我写我自己的比较类调用PercentComparator
并呼吁排序如下collections.sort定义两个元素的排序顺序?
Collections.sort(engineList, new PercentageComparator());
其中engineList
为对象的列表,每个对象都有完成百分比值,高于排序功能工作正常。
现在客户要求按产品类型和百分比添加元素。我们可以按对象的两个元素排序吗?
如果我猜中了:
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
创建您自己的新比较器,比较产品类型后调用PercentageComparator。
我们可以假设Java排序方法是稳定的排序算法吗? – 2012-01-31 20:44:45
Collections.sort是稳定的。从API引用:“例如,排序使用的算法不一定是合并排序,但它必须是**稳定的**。” – msi 2012-01-31 20:47:37
使用番石榴的顺序:'productOrdering.compound(Ordering.from(percentComparator))'依次组合顺序。这可能会稍微方便一些。 (http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Ordering.html) – 2012-01-31 21:57:01
如果将要单独分类,请做一个单独的比较器并将它们用于'连锁'。或者做你的EngineComparator(Boolean sortPercentDesc, Boolean sortProductDesc)
,在我看来这可能会更好,因为会更容易维护。
只要所有相关(可比较)信息都包含在传递给方法的对象中,您的排序方法就可以进行任何类型的排序。换句话说,你的可排序对象应该包含所有可排序的子字段。你将不得不使用不同的排序方法/类来处理它。
如果第一个比较器返回0
,您可以创建一个具有两个比较器的复合比较器,并从第二个比较器返回该值。
您甚至可以使用N个比较器列表来扩展此过程,并返回第一个非零结果,如果达到列表末尾,则返回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;
}
};
如果你想一吨的灵活性,通过各种手段写一堆个体比较,并把它们连一起(正如其他人所建议的那样),但很多时候它会过度杀伤 - 你只需要那个。
感谢您的输入,这是一个很好的解决方案,但对于产品类型而言,优先级高于完成百分比,您的文章很有用。 – skalluri 2012-02-01 17:06:45
首先创建另一个比较器实现,仅比较产品类型。然后调用这样的:
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;
}
}
假设对象是型发动机。
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
对于一个更通用的解决方案,来看看阿帕奇普通的ComparatorChain,来自Javadocs:
ComparatorChain是一个比较器,它依次包装一个或多个比较器。 ComparatorChain按顺序调用每个Comparator,直到1)任何一个Comparator返回一个非零结果(然后返回结果),或者2)ComparatorChain耗尽(并返回零)。这种类型的排序与SQL中的多列排序非常相似,并且该类允许Java类在排序列表时模拟这种行为。
谢谢你,那个作品,同样的例子也在http://stackoverflow.com/questions/4258700/collections-sort-with-multiple-fields – skalluri 2012-02-01 17:05:00