NimChimpsky
NimChimpsky

Reputation: 47290

What is the benefit of using ComparisonChain over Objects.equal() && Objects.equal() ... with Guava

I have just started using google's Guava collection (ComparisonChain and Objects). In my pojo I am overiding the equals method, so I did this first:

return ComparisonChain.start()
         .compare(this.id, other.id)
         .result() == 0;

However, I then realized that I could also use this :

return Objects.equal(this.id, other.id);

And I fail to see when comparison chain would be better as you can easily add further conditions like so:

return Objects.equal(this.name, other.name) 
       && Objects.equal(this.number, other.number);

The only benefit I can see if you specifically need an int returned. It has two extra method calls (start and result) and is more complex to a noob.

Are there obvious benefits of ComparisonChain I missing ?

(Yes, I am also overriding hashcode with appropriate Objects.hashcode())

Upvotes: 13

Views: 16479

Answers (4)

Guido Medina
Guido Medina

Reputation: 466

I would be careful when using Guava's ComparisonChain because it creates an instance of it per element been compared so you would be looking at a creation of N x Log N comparison chains just to compare if you are sorting, or N instances if you are iterating and checking for equality.

I would instead create a static Comparator using the newest Java 8 API if possible or Guava's Ordering API which allows you to do that, here is an example with Java 8:

import java.util.Comparator;
import static java.util.Comparator.naturalOrder;
import static java.util.Comparator.nullsLast;

private static final Comparator<DomainObject> COMPARATOR=Comparator
  .comparingInt(DomainObject::getId)
  .thenComparing(DomainObject::getName,nullsLast(naturalOrder()));

@Override
public int compareTo(@NotNull DomainObject other) {
  return COMPARATOR.compare(this,other);
}

Here is how to use the Guava's Ordering API: https://github.com/google/guava/wiki/OrderingExplained

Upvotes: 4

Louis Wasserman
Louis Wasserman

Reputation: 198211

ComparisonChain is meant to be used in helping objects implement the Comparable or Comparator interfaces.

If you're just implementing Object.equals(), then you're correct; Objects.equal is all you need. But if you're trying to implement Comparable or Comparator -- correctly -- that is much easier with ComparisonChain than otherwise.

Consider:

class Foo implements Comparable<Foo> {
   final String field1;
   final int field2;
   final String field3;

   public boolean equals(@Nullable Object o) {
      if (o instanceof Foo) {
         Foo other = (Foo) o;
         return Objects.equal(field1, other.field1)
             && field2 == other.field2
             && Objects.equal(field3, other.field3);
      }
      return false;
   }

   public int compareTo(Foo other) {
      return ComparisonChain.start()
         .compare(field1, other.field1)
         .compare(field2, other.field2)
         .compare(field3, other.field3)
         .result();
   }
 }

as opposed to implementing compareTo as

 int result = field1.compareTo(other.field2);
 if (result == 0) {
   result = Ints.compare(field2, other.field2);
 }
 if (result == 0) {
   result = field3.compareTo(other.field3);
 }
 return result;

...let alone the trickiness of doing that correctly, which is higher than you'd guess. (I have seen more ways to mess up compareTo than you can imagine.)

Upvotes: 13

Ray
Ray

Reputation: 4869

In the context of overriding methods in your POJOs, I think of a few of Guava's tools matching with a few standard methods.

  • Object.equals is handled using Objects.equals in roughly the manner you mentioned
  • Object.hashCode is handled with Objects.hashCode like return Objects.hashCode(id, name);
  • Comparable.compareTo is handled with ComparisonChain as below:

    public int compareTo(Chimpsky chimpsky) {
        return ComparisonChain.start()
            .compare(this.getId(), chimpsky.getId())
            .compare(this.getName(), chimpsky.getName())
            .result();
    }
    

Upvotes: 2

SLaks
SLaks

Reputation: 887767

ComparisonChain allow you to check whether an object is less-than or greater-than another object by comparing multiple properties (like sorting a grid by multiple columns).
It should be used when implementing Comparable or Comparator.

Objects.equal can only check for equality.

Upvotes: 22

Related Questions