Clean compareTo methods with Google Guava

A common task in object oriented programming is comparing two objects for the purpose of sorting. In Java the useful Comparable<T> Interface exists. I’ve found myself implementing the compareTo method from this Interface plenty of times. But there is something that bothers me everytime: the complexity of the code this implementation creates. Let me explain.

One of my goals is to always write easily readable code. But this is really hard when implementing a compareTo method for an object with more than two fields. Let’s take a look at an example.

public class Fruit implements Comparable<Fruit> {
 
  private String name;
  private String family;
  private int calories;
 
  @Override
  public int compareTo( Fruit otherFruit ) {
    int result = name.compareTo( otherFruit.name );
    if( result == 0 ) {
      result = family.compareTo( otherFruit.family );
      if( result == 0 ) {
        result = Ints.compare( calories, otherFruit.calories );
      }
    }
    return result;
  }  
}

As you can see we have a class called Fruit with three fields. In its compareTo method you can see that all three fields are used for comparison. I think this is a pretty common solution. The downside of this implementation is that every field can influence the compare result. If one field doesn’t have the same value as its counterpart Fruit’s field, the whole Fruit is not the same. This means that after every comparison of a field you need to check the result. This becomes a major drawback when the class evolves. With every new or removed field the compareTo method has to change. In general this is manageable, but the implementation of this method becomes uglier and uglier and transforms into a monster over time. In these cases Google Guava provides a solution called ComparisonChain.

Basically a ComparisonChain is just a util that provides a fluent API to write clean compareTo methods. And, as you might agree, clean means readable and maintanable. Let’s convert the example above using Guavas ComparisonChain.

public class Fruit implements Comparable<Fruit> {
 
  private String name;
  private String family;
  private int calories;
 
  @Override
  public int compareTo( Fruit otherFruit ) {
    return ComparisonChain.start()
      .compare( name, otherFruit.name )
      .compare( family, otherFruit.family )
      .compare( calories, otherFruit.calories )
      .result();
  }
}

The code that performs the checking for the result is completely gone. It’s done for us now by Guava’s implementation. In addition to the nice Interface another cool thing about ComparisionChain’s is that they compare lazily. This means that values will only be compared if the previous comparison was zero. From my point of view the result of using this is much more readable code. As always, feel free to disagree in a comment. icon wink Clean compareTo methods with Google Guava

followme Clean compareTo methods with Google Guava

2 Responses to “Clean compareTo methods with Google Guava”

  1. iskorn says:

    I guess there is a misprint – you meant that “values will only be compared if the previous comparison was zero”

  2. Thanks for the hint. I have updated the post.

2 responses so far

Written by . Published in Categories: Planet Eclipse