Here's why Comparable is not a Functional Interface?

·

4 min read

I got the title but what actually is a functional interface?

Imagine you have a cook in your house. You don't need to tell the cook how to do their job every day. You simply specify what needs to be done—like "make pasta"—and the cook takes care of the rest. Similarly, with a functional interface, you define a task (functionality) that needs to be performed, and the specific implementation of how it will be done is provided elsewhere, often through a lambda expression or method reference.

The key idea is that you focus on defining what to do (the abstract method in the functional interface), not the how (which is implemented later).

By Definition:

A functional interface in Java is an interface that contains exactly one abstract method, making it suitable for use with lambda expressions.

If you want a guy to arrange your books by title, you simply let them know the criteria, and they use a predefined method to figure out how to compare and arrange the books.

Similarly, in Java, the Comparable interface provides a predefined contract for comparing objects. When a class implements this interface, it defines how objects of that class should be compared (like by title, price, or size). Once the comparison logic (via compareTo method) is defined, you don’t have to explain it again and again—it’s automatically used whenever objects of that class need to be compared or sorted.

By Definition:

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.

What about Comparator Interface, seems like it works similar to Comparable. Isn’t it?

In a way, yes… but there’s an important distinction!

Think of it as a difference in who has the authority to compare things.

For example, imagine you want to compare two students based on their age. With the Comparable interface, you’re asking the students to compare themselves directly (this is natural sorting, where each object knows how to compare itself to another).

On the other hand, with the Comparator interface, you’re assigning a third person (a teacher, for example) to compare the students. This allows for custom sorting, where the comparison logic is defined externally.

In short:

  • Comparable: The object itself defines the comparison logic (natural ordering).

  • Comparator: An external class or method defines the comparison logic (custom ordering).

// COMPARABLE INTERFACE EXAMPLE
public class ComparableStudent implements Comparable<ComparableStudent> {
    int age;
    String name;

    ComparableStudent(String name, int age) {
        this.age = age;
        this.name = name;
    }

    @Override
    public int compareTo(ComparableStudent that) {
        this.age < that.age ? return 1 : return -1;
    }
}

// COMPARATOR INTERFACE EXAMPLE
class Student {
    int age;
    String name;

    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class ComparatorExample {
    static Comparator<Student> sortBasedOnStudentAgeUsingLamda() {
        // lambda expression since comparator is a @FunctinalInterface
        Comparator<Student> comp = (arg0, arg1) -> arg0.age > arg1.age ? 1 : -1;

        return comp;
    }
}

public class Main {
    public static void main(String[] args) {
        List<ComparableStudent> list = Arrays.asList(
                new ComparableStudent("Rishi", 10),
                new ComparableStudent("Sushi", 20),
                new ComparableStudent("Khushi", 30),
                new ComparableStudent("Ram", 40),
                new ComparableStudent("Shyam", 50));}

        // Natural sorting 
        System.out.println("Natural order :: " + Collections.sort(list));

        List<Student> students = Arrays.asList(
                    new Student("Rishi", 10), 
                    new Student("Sushi", 20),
                    new Student("Khushi", 30), 
                    new Student("Ram", 40), 
                    new Student("Shyam", 50));    

        Collections.sort(nums, ComparatorExample.sortBasedOnStudentAgeUsingLamda());
        System.out.println("Custom order :: " + nums);

}

So that means we can say Comparable is a Functional Interface too, Right?

Well, the answer is “No!”. Here’s why

While Comparable might seem to qualify because it has only one abstract method, compareTo(), it is not designated as a functional interface because:

  1. Lambda Expression Usage: Comparable is typically implemented by the class itself to provide a natural ordering for its instances. Therefore, using a lambda expression doesn't make as much sense in this context, because you are not going to create multiple different sorting strategies using lambdas with Comparable.

  2. Purpose: The design intent of Comparable is to provide a specific method (compareTo) for objects to determine their natural ordering. Since this usually involves accessing private fields and inherent logic specific to the class, this is best suited to be implemented inside the class rather than externally via lambda expressions.

  3. Design Philosophies: Java's functional interfaces are better suited for actions that can be abstracted and represented by different logic (e.g., Runnable, Callable, Comparator). Comparable, by design, aligns with the object’s intrinsic nature rather than varying logic that might require external handling.

In summary, while Comparable could technically be used as a functional interface, its typical usage pattern and design purpose do not align with the advantages offered by functional interfaces and lambdas.