2012-01-31 32 views
2

我寫我自己的比較類調用PercentComparator並呼籲排序如下collections.sort定義兩個元素的排序順序?

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

其中engineList爲對象的列表,每個對象都有完成百分比值,高於排序功能工作正常。

現在客戶要求按產品類型和百分比添加元素。我們可以按對象的兩個元素排序嗎?

回答

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 
+0

謝謝你,那個作品,同樣的例子也在http://stackoverflow.com/questions/4258700/collections-sort-with-multiple-fields – skalluri 2012-02-01 17:05:00

3

創建您自己的新比較器,比較產品類型後調用PercentageComparator。

+0

我們可以假設Java排序方法是穩定的排序算法嗎? – 2012-01-31 20:44:45

+1

Collections.sort是穩定的。從API引用:「例如,排序使用的算法不一定是合併排序,但它必須是**穩定的**。」 – msi 2012-01-31 20:47:37

+0

使用番石榴的順序:'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

0

如果將要單獨分類,請做一個單獨的比較器並將它們用於'連鎖'。或者做你的EngineComparator(Boolean sortPercentDesc, Boolean sortProductDesc),在我看來這可能會更好,因爲會更容易維護。

0

只要所有相關(可比較)信息都包含在傳遞給方法的對象中,您的排序方法就可以進行任何類型的排序。換句話說,你的可排序對象應該包含所有可排序的子字段。你將不得不使用不同的排序方法/類來處理它。

0

如果第一個比較器返回0,您可以創建一個具有兩個比較器的複合比較器,並從第二個比較器返回該值。

您甚至可以使用N個比較器列表來擴展此過程,並返回第一個非零結果,如果達到列表末尾,則返回0

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

如果你想一噸的靈活性,通過各種手段寫一堆個體比較,並把它們連一起(正如其他人所建議的那樣),但很多時候它會過度殺傷 - 你只需要那個。

+0

感謝您的輸入,這是一個很好的解決方案,但對於產品類型而言,優先級高於完成百分比,您的文章很有用。 – skalluri 2012-02-01 17:06:45

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

} 

假設對象是型發動機。

0

對於一個更通用的解決方案,來看看阿帕奇普通的ComparatorChain,來自Javadocs:

ComparatorChain是一個比較器,它依次包裝一個或多個比較器。 ComparatorChain按順序調用每個Comparator,直到1)任何一個Comparator返回一個非零結果(然後返回結果),或者2)ComparatorChain耗盡(並返回零)。這種類型的排序與SQL中的多列排序非常相似,並且該類允許Java類在排序列表時模擬這種行爲。