2017-02-20 54 views
1

我正在爲jQuery數據表實現服務器端處理。對於那些不熟悉它的人來說,插件允許你對asc/desc列進行排序,以及用單個文本框搜索所有列。由於我的對象列表太大而無法發送到客戶端,我需要通過Java複製它的排序功能。按屬性排序收集,以字符串形式給出

這是我正在使用的對象。每個字段都是客戶端表中的一列。所有字段都是字符串或原語/包裝。

public class MyObject{ 

    String id; 
    String productType; 
    String productGroup; 

    double totalSales; 
    double salesVariance; 

    int vendorId; 
    String vendorName; 
} 

我需要能夠通過任何字段,上升/下降的排序,沒有硬編碼爲每個字段比較功能。

給定一個表示字段名的字符串,我將如何實現一個通用的排序函數?

我目前的解決辦法是處理與犀牛列表... :)

調用犀牛Java方法:

/** 
* @param sortBy - field name 
* @param sortDirection - asc/desc 
*/ 
public void applyFilteringChanges(List<MyObject> myObjects, String sortBy, String sortDirection) throws Exception{ 

    Invocable invocable = (Invocable) engine; 
    invocable.invokeFunction("sortObjects", myObjects, sortBy, sortDirection); 

} 

犀牛代碼:

function sortObjects(myObjects, prop, direction) { 
    var dir = (direction === 'asc') ? 1 : -1; 
    myObjects.sort(function(a,b){ 
     return compare(a,b,prop) * dir; 
    }) 
}; 

function compare(a,b,prop){ 
    if(a[prop] < b[prop]) 
     return -1; 
    else if(a[prop] > b[prop]) 
     return 1; 
    return 0; 
} 

我還涉獵反思,但目前尚不完整。

public void applyFilteringChanges(List<MyObject> myObjects, String sortBy, String sortDirection) throws Exception{ 

     myObjects.sort((s1,s2)->{ 
      Field field; 
      try { 
       field = s1.getClass().getDeclaredField(sortBy); 
       Class<?> type = field.getType(); 
       if(type.isPrimitive()){ 
        //deal with primitive 
       }else{ 
        Comparable o1FieldValue = (Comparable) field.get(s1); 
        Comparable o2FieldValue = (Comparable) field.get(s2); 
        return o1FieldValue.compareTo(o2FieldValue); 
       } 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      return 0; 
     }); 

    } 

我的兩種方法都覺得像黑客,有沒有一種標準的方法來實現這一點?

+2

排序任何屬性的對象,而不對這些屬性提供比較bascially給你留下了這些選項,即使用Java中的反射(您可以使用庫來簡化使用)或將對象轉換爲另一種表示形式(例如,用於Nashorn的JSON,地圖等),然後對其進行排序。但請注意:我不會在每次調用compare()時調用反射代碼,而是在實際排序之前調用反射代碼 - 至少需要檢索字段。 – Thomas

回答

0

您可以創建一個通用的比較是這樣的:

class MyComparator<T extends MyObject> implements Comparator<T> { 

    private String field; 

    public MyComparator(String field) { 
     this.field = field; 
    } 

    @Override 
    public int compare(T o1, T o2) { 
     switch (field) { 
      case "id" : 
       return o1.id.compareTo(o2.id); 

      case "productType": 
       return o1.productType.compareTo(o2.productType); 

      case "productGroup": 
       return o1.productGroup.compareTo(o2.productGroup); 

      //... 
     } 
     return 0; 
    } 
} 

使用方法如下:

public static void main(String[] args) 
{ 
    List<MyObject> objects = new ArrayList<>(); 

    Collections.sort(objects, new MyComparator<>("id")); 
} 
+2

這種做法違反了「沒有爲每個字段硬編碼比較器功能」的要求。「 – Thomas

+0

是的,但作爲他的問題的一部分是「我將如何實現通用分類功能」 –