Как использовать generi c `Number` для` Comparator.comparing` - PullRequest
5 голосов
/ 23 апреля 2020

У меня есть список классов, которые я хочу отсортировать:

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

    // ... getter/setter...
}

И я хочу создать вспомогательный класс (с методами stati c), который можно использовать для сортировки Student list:

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

Тем не менее, вышеприведенный метод принимает только 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

Когда я использую Number вместо Double выдает ошибку The method comparing(Function<? super T,? extends U>) in the type Comparator is not applicable for the arguments (Function<T,Number>)

Мои вопросы:

  1. Почему использование Number вместо Double невозможно?
  2. Как улучшить SortHelper, чтобы использовать Number вместо Double?

Пожалуйста, помогите мне! ..

1 Ответ

5 голосов
/ 23 апреля 2020

Я полагаю, что вы столкнулись с этой проблемой, потому что Comparator#comparing ожидает Function<T, U>, выход которого U расширяется Comparable<? super U>.

Number не реализует Comparable<? super Number>.

Одним из решений является определение нового универсального типа c, который расширяет 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));
}

Или эквивалентно, вы можете использовать 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));
}

Это то, что известно как тип пересечения .

...