5

、我々はこのようなComparable.compareTo(...)を実装しましたこれは:のJava 8のComperator.comparing(...)でCompareToBuilderを交換しthenComparing(...)は、Java 8の前

public int compare(Person a, Person b) { 
    return Comparator 
      .comparing(Person::getLastName) 
      .thenComparing(Person::getFirstName) 
      .compare(a, b); 
} 

新しいJava 8の方法は、私たちはcommons-lang3依存関係をドロップすることが可能かもしれません。 新しいJava 8の方が高速ですか?自動的に移行する方法はありますか? IntelliJの意図が見つかりませんでした。


が逆の注文があり、非自然の比較が関与しているとき、それは少し複雑になっていることに注意してください:

public int compare(SingleBenchmarkResult a, SingleBenchmarkResult b) { 
    return new CompareToBuilder() 
      .append(b.hasAnyFailure(), a.hasAnyFailure()) // Reverse 
      .append(a.getAverageScore(), b.getAverageScore(), resilientScoreComparator) 
      .toComparison(); 
} 

public int compare(SingleBenchmarkResult a, SingleBenchmarkResult b) { 
    return Comparator 
      .comparing(SingleBenchmarkResult::hasAnyFailure, Comparator.reverseOrder()) // Reverse 
      .thenComparing(SingleBenchmarkResult::getAverageScore, resilientScoreComparator) 
      .compare(a, b); 
} 

答えて

2

になり、私はいずれかが存在しているとは思いませんそのための事前定義された検査。 IntelliJのstructural-searchを使用しようとするかもしれませんが、可能性のあるすべてのケースでそれを行うのは非常に難しいかもしれません。 2つの比較での単純なケースのための1つの可能性は、以下のようになります。

検索テンプレート($TYPE$$z$の出現回数である2):

$ReturnType$ $MethodName$($TYPE$ $z$) { 
     return new CompareToBuilder() 
       .append($A$.$m$(), $B$.$m$()) 
       .append($A$.$m1$(), $B$.$m1$()) 
       .toComparison(); 
    } 

交換用テンプレート:

$ReturnType$ $MethodName$($TYPE$ $z$) { 
    return java.util.Comparator 
      .comparing($TYPE$::$m$) 
      .thenComparing($TYPE$::$m1$) 
      .compare($A$, $B$); 
} 

私は構造検索の専門家ではありませんが、多かれ少なかれ比較して通話のパターンを変えなければならないと思います。

6

あなたはそれをこのよう

public int compare(Person a, Person b) { 
    return Comparator 
      .comparing(Person::getLastName) 
      .thenComparing(Person::getFirstName) 
      .compare(a, b); 
} 

を書く場合は、それぞれの比較のための新しいComparatorを構築することで、パフォーマンスを無駄にしています。そして、周囲のコードを見ると明らかに無意味であるはずです。 compare(Person a, Person b)メソッドは確かにComparator<Person>を実装するクラスの一部です。これを使用して、ある場所でインスタンス化して目的のコンパレータを取得します。代わりにのインスタンスをComparator.comparing(Person::getLastName).thenComparing(Person::getFirstName)インスタンスで置き換えて、操作全体を通して使用する必要があります。

など。

// reusable 
static final Comparator<Person> By_NAME = Comparator 
      .comparing(Person::getLastName).thenComparing(Person::getFirstName); 

またはアドホック

listOfPersons.sort(Comparator.comparing(Person::getLastName) 
          .thenComparing(Person::getFirstName)); 

あなたがそのようにそれを使用している場合は、それがより速くなる可能性が非常に高いです。ただし、単純なパターンベースの置換は不可能であることがわかります。そのクラスの使用サイトを単純な宣言的な構造に置き換え、複数の使用サイトに対して共有された比較インスタンスを使用するのか、それを特別に作成するのかを決定する必要があります。その後、古いインプリメンテーションクラス全体を削除するか、少なくともそれが他の目的を果たしている場合はコンパレータ機能を削除します。

+0

私はPersonの自然な比較を実装する必要があるため、これらの変更を適用することはできません。 Comparator.comparing(...)もCompareToBuilderよりも遅いと思いますか? –

+1

自然順序を実装する場合、メソッドは 'compare(Person、Person)'ではなく 'compareTo(Person)'でなければなりません。私は 'Comparator.comparing'を使うのが' CompareToBuilder'よりも遅いとは思っていませんが、私の答えのように 'static final'フィールドを宣言して' compareTo(Person) 'を' BY_NAME.compare(これ、他); 'を返します。 – Holger

+0

良い点。実際には、自然な順序のユースケースがあり、再利用可能なComperator(上記のような)のユースケースがあります。私は、なぜその特化したComperatorを別のクラスにする必要がなくなったのかを理解しています。 –