I understand the get and put principle for collections: if a method takes in a collection that it will write a type T to, the parameter has to be Collection<? super T>, whereas if it will read a type T from, the parameter has to be Collection<? extends T>.
But could someone please explain the Collections.max() signature:
public static <T> T max(Collection<? extends T> coll,
Comparator<? super T> comp)
In particular why is it Comparator<? super T> instead of Comparator<? extends T> ?
Josh Bloch’s mnemonic PECS is useful here. It stands for:
Producer
extends, ConsumersuperThis means that when a parameterized type being passed to a method will produce instances of
T(they will be retrieved from it in some way),? extends Tshould be used, since any instance of a subclass ofTis also aT.When a parameterized type being passed to a method will consume instances of
T(they will be passed to it to do something),? super Tshould be used because an instance ofTcan legally be passed to any method that accepts some supertype ofT. AComparator<Number>could be used on aCollection<Integer>, for example.? extends Twould not work, because aComparator<Integer>could not operate on aCollection<Number>.Edit:
To clarify a little more on get/put (produce/consume):
The above is a method that produces
T.The above is a method that consumes
T.“Producer
extends, Consumersuper” applies to how the method a parameterized object is being passed to is going to be using that object. In the case ofCollections.max(), items will be retrieved from theCollection, so it is a producer. Those items will be passed as arguments to the method onComparator, so it is a consumer.