如何为“Comparator.comparing”使用通用的“Number”

Kim*_*Man 6 java collections comparator

我有一个要排序的课程列表:

class Student {
    private Integer studentId;
    private Double scoreA;
    private Integer scoreB;
    private Long scoreC;

    // ... getter/setter...
}
Run Code Online (Sandbox Code Playgroud)

我想制作一个可用于对Student列表进行排序的辅助类(使用静态方法):

public class SortHelper {
    public static <T> void Sort(List<T> list, Function<T, Double> fn) { // Double
        Collections.sort(list, Comparator.comparing(fn));
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,上述方法只需要Double- 但我想将所有Number对象传递给该方法:

public static <T> void Sort(List<T> list, Function<T, Number> fn) { // `Number`
    Collections.sort(list, Comparator.comparing(fn)); // Error!
}

// so that I can do:
List<Student> students = loadStudents();

SortHelper.Sort(students, Student::getScoreA); // Double
SortHelper.Sort(students, Student::getScoreB); // Integer
SortHelper.Sort(students, Student::getScoreC); // Long
Run Code Online (Sandbox Code Playgroud)

当我使用Number而不是Double,它给出了一个错误The method comparing(Function<? super T,? extends U>) in the type Comparator is not applicable for the arguments (Function<T,Number>)

我的问题是:

  1. 为什么使用NumberDouble不是不可能?
  2. 如何改进SortHelper使用Number而不是Double

请帮帮我..!

Jac*_* G. 5

我相信您正面临这个问题,因为Comparator#comparing期望Function<T, U>其输出U扩展Comparable<? super U>.

Number不执行Comparable<? super Number>

一种解决方案是指定一个新的泛型类型来扩展Number 扩展Comparable

public static <T, U extends Number & Comparable<? super U>> void Sort(List<T> list, Function<T, U> fn) {
    Collections.sort(list, Comparator.comparing(fn));
}
Run Code Online (Sandbox Code Playgroud)

或者等效地,您可以使用List#sort

public static <T, U extends Number & Comparable<? super U>> void Sort(List<T> list, Function<T, U> fn) {
    list.sort(Comparator.comparing(fn));
}
Run Code Online (Sandbox Code Playgroud)

这就是所谓的交叉类型