2017-01-04 14 views
1

Java Comparatorの効果的な使用に関する質問があります。 OPEN、PENDINGとRUNNINGたのアウトなどをキャンセルし条件に基づいて複数のフィールドを使用してソートするためのJavaコンパレータの使用

class MyClass { 
    //Active State: OPEN, PENDING, RUNNING 
    private String state; 
    private Date startDate; 
    private Date endDate; 
} 

ここstateフィールドの可能な値がRUNNING、PENDING、開いている、CLOSEDは、アクティブ状態です。今度は、List<MyClass>をソートし、アクティブなものが最初に来て、でソートされ、続いてendDateに基づいてソートされる非アクティブなものがソートされるコンパレータを書きたいと思います。

static final Set<String> ACTIVE;// this set contains OPEN, PENDING, RUNNING 

List<MyClass> myList;//This is my list 
... 
Collections.sort(myList, new Comparator<MyClass>() { 
    @Override 
    public int compare(MyClass o1, MyClass o2) { 
     int c; 
     boolean isO2 = ACTIVE.contains(o2.getState()); 
     boolean isO1 = ACTIVE.contains(o1.getState()); 
     if (isO2 && isO1) { 
      c = DateTimeComparator.getInstance().compare(o2.getStartDate(), o1.getStartDate()); 
     } else if (isO2) { 
      c = 1; 
     } else if (isO1) { 
      c = -1; 
     } else { 
      c = DateTimeComparator.getInstance().compare(o2.getEndDate(), o1.getEndDate()); 
     } 
     return c; 
    } 
}); 

私の質問は、上記の単一コンパレータの実装が優れているかどうかです。それを行うより良い方法がありますか? ほとんどの場合、Java 7を使用する必要がありますが、Java 8を使用するソリューションも歓迎します。

+2

質問:アクティブな状態が文字列であるのはなぜですか?列挙型はここでより適切ではないでしょうか? –

+0

ところで、私はあなたの実装に問題はありませんが、これに詳しい方がいらっしゃいます。 –

+0

@HovercraftFullOfEels、残念ながら、私たちが所有していないので、残念ながら 'MyClass'に変更を加えることはできません単にそれを使用するだけです。対応するチームにenumを行うように依頼する必要があるかもしれません。 – Learner

答えて

1

Java 8では、Comparator::comparingを使用すると少しきれいになると思います。例:Javaの7では

Comparator<MyClass> comparator = Comparator.nullsFirst(Comparator.comparing((MyClass myClass) -> !isActive(myClass)) 
    .thenComparing((MyClass myClass) -> isActive(myClass) ? myClass.startDate : myClass.endDate, Comparator.nullsFirst(DateTimeComparator.getInstance()))); 

private static boolean isActive(MyClass myClass) 
{ 
    switch (myClass.state) 
    { 
    case "OPEN": 
    case "PENDING": 
    case "RUNNING": 
     return true; 
    default: 
     return false; 
    } 
} 

、あなたがクラスパス上にグアバを持っていると仮定すると、あなたはOrderingを使用することができます。例:

Comparator<MyClass> comparator = Ordering.natural().reverse().onResultOf(new Function<MyClass, Boolean>() { 
     @Override 
     public Boolean apply(MyClass myClass) { 
      return isActive(myClass); 
     } 
    }) 
    .compound(Ordering.from(DateTimeComparator.getInstance()).nullsFirst().onResultOf(new Function<MyClass, Date>() { 
     @Override 
     public Date apply(MyClass myClass) { 
      return isActive(myClass) ? myClass.startDate : myClass.endDate; 
     } 
    })) 
    .nullsFirst(); 
+0

これに相当するJava 7がありますか?これは良いですが。 +1 – Learner

+0

日付はどのように比較されますか?私のソリューションでは、私はDateTimeComparatorを使用しています。日付がジョーダタイムの場合、彼はここで何を使用しますか? – Learner

+0

DateTimeComparatorをthenComparingの2番目のパラメータとして渡すことができます。更新されたコードを参照してください。 – pscuderi

関連する問題