Java 8 个比较器链式反向链接 属性

Java 8 Comparator chaining with a reverse on single property

我正在使用 ComparatorStudent 个对象的列表进行排序。

我想反转 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;
  }

将最后一位更改为:

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

或者,如果您想避免自动装箱:

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

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;
}

我喜欢用Guava's Ordering class for almost all of my sorting. It's very well documented here: https://github.com/google/guava/wiki/OrderingExplained

除其他外,我喜欢 Ordering 因为:

  1. 它使用 "fluent" 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 class 上声明这些常量,这样任何与任何地方的 Student 对象交互的人都可以轻松找到并重用他们对它们进行排序所需的内容。在那种情况下,我可能会将 public 常量命名为 DEFAULT_ORDER 或类似的东西,但如果没有更多上下文,我不确定按 GPA 排序是否是您真正想要的默认设置。

您绝对不必声明四个单独的常量——三个私有常量绝对可以内联声明。我喜欢那样做,因为我发现它提高了可读性。

另外:我不确定你对复制的需求是什么,但如果保证 Students 是唯一的并且你有很好的 equalshashCode 实现,我' d 鼓励您使用 Set<Student> students = new TreeSet<Student>();。这样,它们会在您添加到集合中时进行排序,并且如果您修改集合,它们会自动保持这种状态。