Reputation: 47290
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
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
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
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 mentionedObject.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
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