ソートの見直し

ソートされるSetを作成するのに、いちいち Comparator 実装クラスを書くのは面倒くさくなった。
そこで、一定の Comparator 実装クラスをインジェクトさせる方法を考えた。
でも、当たり前の制約はある。
ソート対象のオブジェクトが Comparable#compareTo を実行できるインスタンス
取得するメソッドを公開(public)できることである。

import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.TreeSet;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;

public final class TreeSetFactory{
   private TreeSetFactory(){}
   // ソート対象のクラスと Comparable#compareTo を実行できるインスタンスを取得する getter 名を指定
   @SuppressWarnings("unchecked")
   public static <T> TreeSet<T> createASC(final Class<T> cls,final String getterName){
     Injector injector = Guice.createInjector(new AbstractModule(){
            @Override
            protected void configure(){
               try{
               binder().bind(Method.class).toInstance(cls.getMethod(getterName));
               }catch(Exception e){
                  throw new RuntimeException(e);
               }
               binder().bind(Comparator.class).to(AscComparator.class);
            }
         }
      );
      return injector.getInstance(StencilTreeSet.class);
   }
   public static <T> TreeSet<T> createUniqueASC(final Class<T> cls,final String getterName){
      Injector injector = Guice.createInjector(new AbstractModule(){
            @Override
            protected void configure(){
               try{
               binder().bind(Method.class).toInstance(cls.getMethod(getterName));
               }catch(Exception e){
                  throw new RuntimeException(e);
               }
               binder().bind(Comparator.class).to(AscUniqueComparator.class);
            }
         }
      );
      return injector.getInstance(StencilTreeSet.class);
   }
   // 降順も同様に用意する。
   // binder().bind(Comparator.class).to で指定するクラスは以下
   // DescComparator.class       → 重複許可の降順
   // DescUniqueComparator.class → 重複させない降順
}
============================================
import java.lang.reflect.Method;
import java.util.Comparator;
import com.google.inject.Inject;
// 重複許可の昇順
class AscComparator<T> implements Comparator<T>{
   @Inject private Method getterMethod;
   @SuppressWarnings("unchecked")
   @Override
   public int compare(T o1,T o2){
      try{
      return *1.compareTo*2 >= 0 ? 1 : -1;
      }catch(Exception e){
         throw new RuntimeException(e);
      }
   }
}
// 重複させない昇順(先行が残る)
class AscUniqueComparator<T> implements Comparator<T>{
   @Inject private Method getterMethod;
   @SuppressWarnings("unchecked")
   @Override
   public int compare(T o1,T o2){
      try{
      return *3.compareTo*4;
      }catch(Exception e){
         throw new RuntimeException(e);
      }
   }
}
// 重複許可の降順
class DescComparator<T> implements Comparator<T>{
   @Inject private Method getterMethod;
   @SuppressWarnings("unchecked")
   @Override
   public int compare(T o1,T o2){
      try{
      return *5.compareTo*6 >= 0 ? -1 : 1;
      }catch(Exception e){
         throw new RuntimeException(e);
      }
   }
}
// 重複させない降順(先行が残る)
class DescUniqueComparator<T> implements Comparator<T>{
   @Inject private Method getterMethod;
   @SuppressWarnings("unchecked")
   @Override
   public int compare(T o1,T o2){
      try{
      return -1 * *7.compareTo*8;
      }catch(Exception e){
         throw new RuntimeException(e);
      }
   }
}
============================================
import java.util.Comparator;
import java.util.TreeSet;
import com.google.inject.Inject;

class StencilTreeSet<T> extends TreeSet<T>{
   @SuppressWarnings("unchecked")
   @Inject
   protected StencilTreeSet(Comparator c){
      super(c);
   }
}
============================================
Setの作成例、
   Sampleオブジェクトのソート対象の属性が日付で、getter名が、"getDate"である時

   Set<Sample> set = TreeSetFactory.createASC(Sample.class,"getDate");

*1:Comparable<T>)this.getterMethod.invoke(o1

*2:T)this.getterMethod.invoke(o2

*3:Comparable<T>)this.getterMethod.invoke(o1

*4:T)this.getterMethod.invoke(o2

*5:Comparable<T>)this.getterMethod.invoke(o1

*6:T)this.getterMethod.invoke(o2

*7:Comparable<T>)this.getterMethod.invoke(o1

*8:T)this.getterMethod.invoke(o2