Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Comparable and Comparator are consumers in PECS wildcard types in Java

In Effective Java, in the item "Use bounded wildcards to increase API flexibility", when talking about the usage of PECS (producer-extends, consumer-super), the author mentioned that:

Comparables are always consumers, so you should generally use Comparable<? super T> in preference to Comparable. The same is true of comparators; therefore, you should generally use Comparator<? super T> in preference to Comparator.

It is not clear to me why Comparables and Comparators are considered consumers.

In one of the topic discussing PECS, What is PECS (Producer Extends Consumer Super)?, the consumer is usually referring to a Collection as a parameter for some generic method.

While here Comparable is just an interface.

Can anyone share some insights? Thanks!

like image 945
cxs1031 Avatar asked Dec 18 '22 12:12

cxs1031


2 Answers

A nice analogy can be drawn to the interfaces Consumer<T> and Supplier<T> (with Supplier being analogous to Producer). A Consumer<T> is a function that takes in a T, while a Supplier<T> is a function that returns a T. Notice that we are talking about method signatures and return type, we say nothing about the semantics of the method. This is a core property of PECS: it is independent of the semantics and can be determined solely on the signature and return type of the methods used.

Looking at Comparable<T> and Comparator<T>, we find that both have methods (int compareTo(T) and int compare(T, T)) that take in, i.e. consume, T's.

For the collections, we have to look on how we use the collection, i.e. if we are using producer- or consumer-methods:

  • If we retrieve data from the collection (T get(int), iterator, ...), the list produces values for us and we use ? extends T.
  • If we use the collection to store data, (i.e. we call add(T), addAll(Collection<T>), contains(T), ...), we call consuming methods, thus the method is a consumer of our data and we use ? super T.
  • If we use a collection to both store and retrieve values, the collection acts as a consumer and producer at the same time, thus we have to use the precise T, neither using ... extends ... nor ... super ....
like image 78
Turing85 Avatar answered Dec 20 '22 03:12

Turing85


…It is not clear to me why Comparables and Comparators are considered consumers.…“

Anytime a method member of a generic class C<T>, takes in (i.e. „consumes“) an argument that is of type T, then that method is a consumer of Ts.

So Comparator<T>.compareTo(T o) is said to be a „consumer“ of the o object of the type represented by the type variable T.

like image 34
deduper Avatar answered Dec 20 '22 02:12

deduper