Java generics: Collections.max() подпись и компаратор

Я понимаю получить и поместить принцип для коллекций: если метод берет в коллекции, что он будет писать тип T to, параметр должен быть Collection<? super T>, тогда как если он будет читать тип T, параметр должен быть Collection<? extends T>.

Но кто-то может объяснить Collections.max() подпись:

public static <T> T max(Collection<? extends T> coll,
                    Comparator<? super T> comp)

В частности, почему он Comparator<? super T> вместо Comparator<? extends T>?

Ответ 1

Josh Bloch Мнемонический PECS полезен здесь. Это означает:

Производитель extends, Потребитель super

Это означает, что когда параметризованный тип, передаваемый методу, генерирует экземпляры T (они будут извлечены из него каким-либо образом), следует использовать ? extends T, поскольку любой экземпляр подкласса T также является T.

Когда параметризованный тип, передаваемый методу, будет потреблять экземпляры T (они будут переданы ему, чтобы что-то сделать), следует использовать ? super T, потому что экземпляр T может быть юридически передан любому метод, который принимает некоторый супертип T. Например, A Comparator<Number> можно использовать на Collection<Integer>. ? extends T не будет работать, поскольку Comparator<Integer> не может работать с Collection<Number>.

Edit: Чтобы прояснить немного больше о get/put (производить/потреблять):

public T something();
       ^

Вышеупомянутый метод, который создает T.

public void something(T t);
                      ^

Вышеупомянутый метод, который потребляет T.

"Производитель extends, Потребитель super" применяется к тому, как метод, которым параметризованный объект передается, будет использовать этот объект. В случае Collections.max() элементы будут извлекаться из Collection, поэтому он является производителем. Эти элементы будут переданы в качестве аргументов методу на Comparator, поэтому он является потребителем.

Ответ 2

Компаратор потребляет пару Ts и производит int. Коллекция производит Ts, который потребляет компаратор.

Супер потребляет, расширяет производит.

В отношении принципа get и put get производит и потребляет потребление.

Ответ 3

Компаратор должен иметь возможность принимать T в качестве аргумента.