开发者

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

开发者 https://www.devze.com 2023-03-25 17:05 出处:网络
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:

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.e开发者_JAVA百科qual(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())


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.


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.)


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();
    }
    


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

0

精彩评论

暂无评论...
验证码 换一张
取 消