我寫我自己的比較類調用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