Solution ExSheet 11, Task 2 / 4, Comparable and Comparators

Hello everyone :slight_smile:

I’m confused about when to use the additional implements Comparable<T> for the Class of T and when not, when it comes to Comparators.
Here’s what I mean:

Task 2 states that we should sort the items of the collection participants (which is a collection of Objects of Type Person) using a Comparator<Person> called “PersonComparator”. While the solution shows how to implement the Comparator itself, it does not show us any necessary changes for the comparable Class Person.

Nevertheless, in task 4, it does. The solution states, that we have to extend the class definition of “Cow”, which is again the type of objects, we want to compare, by the phrase implements Comparable<Cow>. Also, we don’t use a Comparator here.

So my question is: What’s the exact difference between Comparators and Comparable Objects? When do we need to add phrases like implements Comparable<T> and when is it sufficient to just implement a Comparator and leaving the Object we want to compare just as it is.

Thanks in advance,
David


//Edit: Would a Comparator also be a sufficient solution? Like, I could implement a comparator of type Cow, as seen in Task 2, and then use Collections.sort(cows, new CowComparator());

Exercise 2.: Lottery

Exercise 4.: Farmer John and his Cows

Neither of the two exercises states that you have to use one or the other method.
Both are solution proposals that show a way the exercise might be used.
Exercise two for instance only states that you should read up on Comparators in Java and that they might be helpful.
Here are the documentations:

Both have quite similar methods:

int compare(T o1, T o2)
int compareTo(T o)

that impose a total ordering on elements and that should be consistent with equality:

\forall e_1, e_2.~ e1.compareTo(e2) == 0 \Leftrightarrow e1.equals(e2)
\forall e_1, e_2.~ c.compare(e1, e2)==0 \Leftrightarrow e1.equals(e2)

The main difference is whether the comparison is in the class itself or as an additional class.
Usually, the distinction is made to use one or the other depending on whether the comparison is intrinsic to the type and in what context it will be used.

See the documentation of Comparator for more examples/explanations.

Can you answer that question with help of the documentation?

1 Like

Alright, gotcha, thank you.

So, to summarize: Both types would be a possible approach to sort a collection?

So in our case, we should be able to use both options for task 4 too, right? If we want to use the Cow as comparable object, we need to implement the Comparable<Cow> interface first (to provide necessary methods like compareTo which also states the type of sorting). And if we want to use a Comparator, we implement a Class like CowComparator which implements the Comparator<Cow> interface, which then can be used as “tool” for e.g Collections.sort(), very similar to Array.sort() and so on.

In my understanding, this works like we were used to implement sorting functions last semester in Prog1. When we implemented sorting with e.g fold, we were always told to pass a function f, functioning as a “Comparator”, so to say.

Yes, the sorting function from collections is defined twice:

  • Once for comparable types
  • Once for all types if you provide a comparator

As mentioned, you have to be able to modify the class in order to use Comparable.
Also, the comparison order is intrinsic (also called natural) to the type for Comparable.
With Comparator, you can simply plug in another Comparator for another sorting order (like reversed).

Note: A Comparator could also be stateful or parametric.

Yes.

Yes, the comparator acts as the comparator function argument in the higher-order sorting function from Prog1.

1 Like