0

I'm new here and this is my first post. I've just completed my Java OCA and now moving onto studying for the OCP. I have a question regarding Comparable interface.

I have this code snippet which explains how Comparable is implemented:

import java.util.*;
public class Duck implements Comparable<Duck> {
private String name;
public Duck(String name) {
this.name = name;
}
public String toString() {   // use readable output
return name;
}
public int compareTo(Duck d) {
return name.compareTo(d.name); // call String's compareTo
}
public static void main(String[] args) {
List<Duck> ducks = new ArrayList<>();
ducks.add(new Duck("Quack"));
ducks.add(new Duck("Puddles"));
Collections.sort(ducks); // sort by name
System.out.println(ducks); // [Puddles, Quack]
}
}

I more or less understand what is goin on here but below this code snippet the author quotes that:

The Duck class implements the Comparable interface. Without implementing that interface, all we have is a method named compareTo(), but it wouldn't be a Comparable object.

My question is why would it not be comparable? Is this something to do with the fact that calling code such as the Collections.sort() would internally use the Comparable type as a reference parameter to compare any object?

Thanks in advance for any help and I hope my question makes sense.

Bobby Iveson
  • 133
  • 8

2 Answers2

1

My question is why would it not be comparable? Is this something to do with the fact that calling code such as the Collections.sort() would internally use the Comparable type as a reference parameter to compare any object?

I'm not sure what you exactly mean by reference parameter.

In Java, it is not enough for a class to provide implementation for a method on an interface (or a class) to become that type. It has to be explicitly mentioned in the class declaration.


There are two overloaded sort utility methods on the Collection class.

public static <T extends Comparable<? super T>> void sort(List<T> list)

public static <T> void sort(List<T> list, Comparator<? super T> c)

When your class implements Comparable, you can pass just the list of objects of that class in the first method. If it does not implement Comparable, it will not compile as the bounds for T must extend Comparable. In that case, you will be forced to pass an explicit Comparator to compare the objects.

As the author of the book mentioned, having a method whose signature is the same as the method in an arbitrary interface (or class) does not make it of that type.

Duck Typing does not work in Java

Thiyagu
  • 17,362
  • 5
  • 42
  • 79
  • Thanks for your answer... It is much appreciated. I was more concerned with the internal implementation of the sort method, to be honest. When I say reference parameter I mean the fact that somewhere internally the sort method would use a referance to a comparable object to call the compareTo method by assigning one of these object to a comparable reference. I was trying to understand internally how the sort method is implemented. – Bobby Iveson Mar 31 '20 at 02:04
1

Java is a Object Oriented Based language. Which supports inheritance through classes/ polymorphism through class/abstract class/interface

interface Comparable<T> {
  // methods
}

class Person implements Comparable<Person> {
//methods
}

This essentially means any object of the Type Person is also of the Comparable Type.

interface Runnable {}
class Task implements Runnable {}

this means any object created of Task class is also of the Runnable Type.

This is what the author means.

If you do not implement Comparable interface, yet define the compareTo() method, you are just defining a method inside the class, as any other method. YOU ARE NOT OVERRIDING THE compareTo() method in the Comparable interface defined.

You can still compare each object using your compareTo() method, but you need to define your own sort method which internally would call compareTo() method to get the list in a sorted way.

The Java API Collections.sort() internally converts the list to an Object[] and calls the Arrays.sort(). Now Arrays.sort() will use a modified version of the TimSort Algorithm for sorting and the contract is - it does the sorting of elements of the Array only if they are of the Comparable Type.

  • ComparableTimSort
  • Collections.sort()

You can check, for all of the internal calls, it states clearly :

@throws IllegalArgumentException (optional) if the comparator is found to violate the {@link Comparator} contract

So to pass any Object Types to the sort() it has to be also of the type Comparable. Strings/Wrappers are already of the Comparable Type. Hence you need to take care of this contract while defining your user defined objects.

"Without implementing that interface, all we have is a method named compareTo(), but it wouldn't be a Comparable object."

-Simply put, it means without implementing the interface, you have a Duck type object, NOT comparable type

Priyak Dey
  • 1,227
  • 8
  • 20
  • Thanks, I really appreciate your answer. I more or less understand what you are saying but I was really implying about how the sort method uses the comparable objects within in it's method. I wasn't aware of the TimSort and I'm guessing the fact that the sort takes a comparable object means that it will call the compareTo() method on each element of the list and internally sort using the TImSort, somehow. – Bobby Iveson Mar 31 '20 at 00:02
  • In case you using Eclipse (or any IDE) you can move your mouse over to the method /class and then contrl/cmd + left click on it to checks its implementation. So you can see how the sort method is being implemented. – Priyak Dey Mar 31 '20 at 08:36