2017-02-20 14 views
1

jQueryデータ型のサーバーサイド処理を実装しています。それに精通していない人のために、プラグインを使用すると、列asc/descをソートしたり、すべての列を単一のテキストボックスで検索することができます。オブジェクトの私のリストはクライアントに送るには大きすぎるので、私はそれをJavaを介して機能を並べ替える必要があります。プロパティを指定してコレクションをソートします。文字列として指定します。

これは私が扱っているオブジェクトです。各フィールドは、クライアント側の表の列です。すべてのフィールドは文字列かプリミティブ/ラッパーです。

public class MyObject{ 

    String id; 
    String productType; 
    String productGroup; 

    double totalSales; 
    double salesVariance; 

    int vendorId; 
    String vendorName; 
} 

私はハードは各フィールドのコンパレータ機能をコーディングせず、フィールド、昇順/降順のいずれかでソートできるようにする必要があります。

フィールド名を表す文字列を指定すると、汎用ソート関数はどのように実装されますか?

私の現在のソリューションは、Nashornでリストを処理することである

... Nashornを呼び出します:)

Javaメソッド:私も手を出し

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

/** 
* @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); 

} 

Nashornコード反射、しかしそれは現時点では不完全です。

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でリフレクションを使用するか(ライブラリを使用してより簡単に使用することができます)、オブジェクトを別の表現(JSON、例えばNashorn、マップなど)に変換して並べ替えます。 1つのメモ:私はすべての 'compare()'呼び出しでリフレクションコードを呼び出すのではなく、実際にソートする前に1回、つまり少なくともフィールドの取得を呼びます。 – 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

はい、彼の質問の一環として、「どのようにジェネリックソート機能を実装するのですか? –

関連する問題