27

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> ?

Jason S
  • 184,598
  • 164
  • 608
  • 970

3 Answers3

66

Josh Bloch's mnemonic PECS is useful here. It stands for:

Producer extends, Consumer super

This 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 T should be used, since any instance of a subclass of T is also a T.

When a parameterized type being passed to a method will consume instances of T (they will be passed to it to do something), ? super T should be used because an instance of T can legally be passed to any method that accepts some supertype of T. A Comparator<Number> could be used on a Collection<Integer>, for example. ? extends T would not work, because a Comparator<Integer> could not operate on a Collection<Number>.

Edit: To clarify a little more on get/put (produce/consume):

public T something();
       ^

The above is a method that produces T.

public void something(T t);
                      ^

The above is a method that consumes T.

"Producer extends, Consumer super" applies to how the method a parameterized object is being passed to is going to be using that object. In the case of Collections.max(), items will be retrieved from the Collection, so it is a producer. Those items will be passed as arguments to the method on Comparator, so it is a consumer.

ColinD
  • 108,630
  • 30
  • 201
  • 202
1

The Comparator consumes a pair of Ts and produces an int. The Collection produces the Ts the comparator consumes.

Super consumes, extends produces.

In relation to the get and put principle, get produces and put consumes.

ILMTitan
  • 10,751
  • 3
  • 30
  • 46
0

The comparator needs to be able to take a T as an argument.

Anon.
  • 58,739
  • 8
  • 81
  • 86
  • 6
    I recommend reading the chapter of Effective Java that discusses "PECS", then. And think about it this way: if I asked you to sort a list of Doubles, and gave you a Comparator to do it with, how would you feel about that? – Kevin Bourrillion Feb 12 '10 at 17:36
  • Could you expand your answer? While the answer may be clear for advanced java programmers, it requires rereading the question to fully understand what you are saying. I know this could be one of your earlier answers, but it appears at the Low Quality posts review section. - [From review](https://stackoverflow.com/review/low-quality-posts/11445740) – Ferrybig Feb 29 '16 at 08:53