web-dev-qa-db-ja.com

Java 8単一プロパティでリバースを使用したコンパレータチェーン

Comparatorを使用してStudentオブジェクトのリストを並べ替えています。

idプロパティの並べ替えを逆にしたいのですが、reverse()メソッドを使用すると、並べ替え全体に適用されます。

idでのみ発生させる方法は?

これまでの私のコードは次のとおりです。

 public List<Student> getStudents(List<String> events) {
    Comparator<Student> comparatorStudents = Comparator.comparing(Student::getCGPA).thenComparing(Student::getName)
      .thenComparingInt(Student::getID).reverse();
    List<Student> students = new ArrayList<Student>();
    //Filling students
    Collections.sort(students, comparatorStudents);
    return students;
  }
13
Logan Wlv

最後のビットを次のように変更します。

.thenComparing(Student::getID, Comparator.reverseOrder())

または、オートボクシングを避けたい場合:

.thenComparing(Comparator.comparingInt(Student::getID).reversed())
7
shmosel

reversed() の呼び出しをthenComparing内に置きます。

public List<Student> getStudents(List<String> events) {
    Comparator<Student> comparatorStudents = Comparator.comparing(Student::getCGPA)
       .thenComparing(Student::getName)
       .thenComparing(Comparator.comparingInt(Student::getID).reversed());
    List<Student> students = new ArrayList<Student>();
    //Filling students
    Collections.sort(students, comparatorStudents);
    return students;
}
2
dasblinkenlight

私はほとんどすべてのソートに GuavaのOrdering class を使用するのが好きです。ここで非常によく文書化されています: https://github.com/google/guava/wiki/OrderingExplained

とりわけ、私はOrderingが好きです。理由は次のとおりです。

  1. 「流暢な」APIを使用します。
  2. 注文はComparableを実装しているため、Comparableを使用できる場所であればどこでも使用できます。
  3. それらは当然スレッドセーフです(つまり、静的定数として宣言し、どこでも単一のインスタンスを再利用できます)。

あなたの場合、私は次のようにコードを書きます:

_private static final Ordering<Student> BY_GPA = Ordering.natural().onResultOf(Student::getCGPA);
private static final Ordering<Student> BY_NAME = Ordering.nautural().onResultOf(Student::getName);
private static final Ordering<Student> BY_ID_DESCENDING = Ordering.natural().reverse().onResultOf(Student::getID);

// I spent approximately zero time coming up with a good name for this constant
public static final Ordering<Student> STUDENT_ORDER = BY_CPA.compound(BY_NAME).compound(BY_ID_DESCENDING);

public List<Student> getStudents(List<String> events) {
    List<Student> students = new ArrayList<Student>();
    //Filling students
    Collections.sort(students, STUDENT_ORDER);
    return students;
}
_

個人的には、私は通常、Studentクラスでこれらの定数を宣言します。これにより、どこでもStudentオブジェクトを操作する人は誰でも、それらを並べ替えるのに必要なものを簡単に見つけて再利用できます。そのシナリオでは、おそらくパブリック定数_DEFAULT_ORDER_などの名前を付けますが、コンテキストがないと、GPAによる並べ替えが本当に必要なデフォルトであるかどうかわかりません。

4つの別々の定数を宣言する必要は絶対にありません。3つのプライベート定数は絶対にインラインで宣言できます。読みやすさが向上するので、そうするのが好きです。

また、複製に関してあなたのニーズが何であるかはわかりませんが、学生が一意であることが保証されており、equalshashCodeの適切な実装がある場合は、お勧めしますSet<Student> students = new TreeSet<Student>();を使用します。そうすれば、コレクションに追加するときに並べ替えられ、コレクションを変更しても自動的に並べ替えられます。

1
JakeRobb