2012-01-16 10 views
2

このループからリフレクションを引き出し、可能であればゲッターメソッドを渡すにはどうすればよいですか?このループから反射を取り除くにはどうすればよいですか?

public <E> void sortBy(final String fieldName, final boolean sortAsc, List<E> list){ 
     Collections.sort(list, new Comparator<E>() { 
       public int compare(E o1, E o2) { 
        return compareFields(o1,o2,fieldName.replace("SortBy", "get"),sortAsc); 
       } 
      } 
     ); 
    } 

    @SuppressWarnings({ "rawtypes", "unchecked" }) 
    protected <E> int compareFields(E o1, E o2,String fieldName, boolean sortAsc){ 
     try { 
      Comparable o1Data; 
      Comparable o2Data; 
      o1Data = (Comparable) o1.getClass().getMethod(fieldName).invoke(o1); 
      o2Data = (Comparable) o2.getClass().getMethod(fieldName).invoke(o2); 
      if(o1Data == null && o2Data == null){ 
       return 0; 
      } else if (o1Data == null){ 
       return 1; 
      } else if (o2Data == null){ 
       return -1; 
      } 
      int result = o2Data.compareTo(o1Data); 
      return (sortAsc) ? -result : result ; 
     } 
     catch(Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

コンテキスト:私はデータテーブルを持つ多くの画面があります。それぞれはリストから構築されます。各データテーブルは、6つの各列によってソート可能でなければなりません。列は、日付または文字列です。

答えて

2

すべての要素が同じタイプであると想定できる場合は、

public <E> void sortBy(final String fieldName, final boolean sortAsc, List<E> list) throws NoSuchMethodException { 
    final Method f = list.get(0).getClass().getMethod(fieldName.replace("SortBy", "get")); 
    f.setAccessible(true); 
    final int direction = sortAsc ? +1 : -1; 
    Collections.sort(list, new Comparator<E>() { 
     public int compare(E o1, E o2) { 
      return compareFields(o1, o2, f, direction); 
     } 
    } 
    ); 
} 

@SuppressWarnings({"rawtypes", "unchecked"}) 
protected <E> int compareFields(E o1, E o2, Method getter, int sortAsc) { 
    try { 
     Comparable o1Data = (Comparable) getter.invoke(o1); 
     Comparable o2Data = (Comparable) getter.invoke(o2); 
     if (o1Data == null) 
      return o2Data == null ? 0 : 1; 
     if (o2Data == null) 
      return -1; 
     return sortAsc * o2Data.compareTo(o1Data); 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
} 
2

getFieldByNameメソッドを含むインターフェイスをデータオブジェクトに実装させます。

+0

+1、良いアイデア。また、実際にアクセス可能なフィールドを見つけるために 'getAvailableFields'をインターフェースに追加します。最も良いことは、あなたが実際に反射を完全に避けていることです。 –

+0

私が間違っていると私を訂正してください。しかし、私がパフォーマンスの観点から見た問題は、そのロジックをソート/比較ループから抜け出せないということです。 – Dale

+0

これがあなたのボトルネックになったら、 'getAccessorByName'を持つことができます。ここで' Accessor'はあなたのオブジェクトを受け取り、対応するフィールドを返す 'getValue'メソッドを持っています。次に、データオブジェクトの実装を考慮して、アクセサの作成時にルックアップやその他の準備を行うことができます。パフォーマンスが求められたら、私はリフレクションを信用しません。私の実験では遅いですが、原理的には効率的に実装できるので新しいバージョンでは速くなる可能性があります。 –

1

Apache Bean Utilsは、この種のものには非常に便利です。

ここ
... 

Comparable o1Data = (Comparable) PropertyUtils.getProperty(o1, fieldName); 
Comparable o2Data = (Comparable) PropertyUtils.getProperty(o2, fieldName); 
if(o1Data == null && o2Data == null) { 

... 

fieldNameは、プロパティ/フィールドの名前ではなく、ゲッターする必要があります:彼らは、最も可能性の高い使用の反射、内部でそれはあなたがする必要はありません、あなたは素敵なきれいなコードを持っていることを意味します。あなたのコードの変数はゲッターの名前を保持しているので、代わりにgetterNameのように呼び出すべきでしょう。

関連する問題