Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8: implementing Comparable

I like the new static factory methods of Comparator, as they allow to implement Comparators in a very concise and less error-prone way.

But what is the recommended way to implement Comparable? Should we use Comparators inside the Comparable implementation?

public MyClass implements Comparable<MyClass>{
...
    public int compareTo(MyClass other){
        Comparator<MyClass> naturalOrderComparator = 
            Comparator.comparing(MyClass::getFoo)
                      .thenComparing(MyClass::getBar);
        return naturalOrderComparator.compare(this, other);
    } 
}

or even use a static comparator to reduce a lot of object creation when sorting huge collections:

public MyClass implements Comparable<MyClass>{
    private static final Comparator<MyClass> NATURAL_ORDER_COMPARATOR =     
        Comparator.comparing(MyClass::getFoo)
                  .thenComparing(MyClass::getBar);

    ...

    public int compareTo(MyClass other){
        return NATURAL_ORDER_COMPARATOR.compare(this, other);
    } 
}

Or is there another recommended way to implement Comparable with Java SE 8?

like image 460
Puce Avatar asked Sep 18 '17 18:09

Puce


People also ask

What is implement comparable in Java?

The Comparable interface is used to compare an object of the same class with an instance of that class, it provides ordering of data for objects of the user-defined class. The class has to implement the java. lang.

Can we implement comparable interface?

We can implement the Comparable interface with the Movie class, and we override the method compareTo() of Comparable interface.

What is implement comparable?

Comparable is used to compare instances of your class. We can compare instances from many ways that is why we need to implement a method compareTo in order to know how (attributes) we want to compare instances.


2 Answers

Your own Option 2 is almost certainly the best currently available way. It avoids allocation, it reads pretty well -- especially if you put the static constant next to the compareTo method.

The new Comparator.comparing factory methods in Java 8 are very easy to read, and even better, difficult to screw up -- there are many, many ways to write comparisons incorrectly by hand, more than I care to remember, and the factory methods are immune to most of them. Even though it's a little weird to use them to write a compareTo method instead of a Comparator object, it's still better than the alternatives.

like image 113
Louis Wasserman Avatar answered Sep 18 '22 12:09

Louis Wasserman


Pre-Java-8 the general best practice was to use Guava's ComparisonChain and Ordering utilities. They abstract away the cumbersome and easy-to-get-wrong details of properly implementing a .compareTo()/.compare() method, and allow you to compose a human-readable sequence of steps to define how objects should be compared. Ordering implements Comparator, but there'd be nothing wrong with defining an Ordering and invoking it in a Comparable's .compareTo() method.

Note that Ordering is described as obsolete thanks to the additions to the JDK in Java 8:

If you are using Java 8, this class is now obsolete.... Most of its functionality is now provided by Stream and by Comparator itself, and the rest can now be found as static methods in our new Comparators class.

like image 37
dimo414 Avatar answered Sep 19 '22 12:09

dimo414